Commit graph

22 commits

Author SHA1 Message Date
7b5cf5f918 fix(ci): remove duplicate web job (yaml parse error) 2026-08-31 22:15:58 +00:00
5eec24d656 fix(ci): go 1.26.x -> 1.22.x (1.26 not released) 2026-08-31 22:15:33 +00:00
ae13e72241 chore: retrigger ci 2026-08-31 22:14:20 +00:00
ee24a5e304 chore: remove Render configs, point docs at VPS domains 2026-08-31 22:08:15 +00:00
d892c9a9fc ci: add deploy workflow (build linux/amd64 to GHCR + SSH deploy to VPS) 2026-08-31 22:02:25 +00:00
8f17c42c65
test(core): cover the review fixes; scope history gaps; guard record --server
Adds regression tests for the fixed-width timestamp format and sub-second
boundaries, in-memory store dedup and cursor pagination, stream-ID selector
escaping, live-vs-synthetic event IDs, gap healing and baseline state reset,
path-scoped diff ignores, nested Added/Removed flags, snapshot watermarks and
the TypeSnapshot record, NodePort/headless service sanitization, the
dry-run-gated apply, skipped-object reporting, and the expanded gvrFor table.
The object-history endpoint now scopes gap markers to the requested window,
and record --server fails loudly instead of silently recording locally.
2026-08-06 07:01:21 +05:30
9f4b6c2c5a
fix(audit,web,deploy): audit ids, web dry-run view, hardened chart, docs
Audit: correlation event_ids include stage and response code so the
multi-stage lines of one request no longer collapse under dedup; match
scans are bounded to a time window and a page instead of the object's full
history.

Web: dry-run results are read from dry_run_result (nested) so the verdict is
rendered correctly and conflicts/errors/skipped are shown; the plans view no
longer POSTs an unsolicited plan on page load; coverage and streams surface
API errors instead of showing a misleading empty state and follow cursor
pagination so they are not stuck on the oldest page; the diff path tokenizer
handles backslash-escaped dotted keys.

Deploy/CI: the chart no longer grants the query server a cluster-wide read
ClusterRole, runs as non-root with a read-only root filesystem, adds
liveness/readiness probes, wires the ConfigMap as env (STORE_PATH,
LISTEN_ADDR), defaults the journal to a PVC instead of an ephemeral
emptyDir, and adds imagePullSecrets; the replay ClusterRole drops the
unused update verb; a Dockerfile builds a static distroless image; GitHub
actions are pinned by commit SHA, jobs set least-privilege permissions, the
Vercel deploy skips fork PRs, CI passes the Makefile test timeouts, and
make lint runs a real web syntax check.

Docs: event-schema/consistency no longer describe an ingest_sequence field,
an observed-time-based event_id, or restart-from-checkpoint; the threat
model documents the unauthenticated HTTP API surface and the chart's RBAC
change; replay-safety matches the enforced dry-run gate.
2026-08-06 06:57:11 +05:30
44fbd878a1
fix(core): storage time ordering, watch state machine, replay safety, API pagination
Storage: fixed-width millisecond timestamp format with a one-time migration
so lexicographic comparisons stay chronological; snapshot auto-IDs get
nanosecond precision; Close is synchronized; commit failures roll back; DSN
paths are URI-escaped; the dedup index is no longer rebuilt every startup;
the in-memory store now dedups by event_id and honors Limit/Offset/SinceSeq.

Event/discovery: stream IDs URL-escape the selector so slash-containing label
selectors round-trip and cannot collide; alias resolution fills empty fields
only and no longer clobbers explicit group/version/kind; rc maps to
replicationcontrollers and rs to replicasets.

Watch: the label selector is now actually applied to List and Watch; the 410
relist path is backoff-throttled, backoff resets after a healthy watch, an
empty list resourceVersion backs off instead of looping forever, non-410
watch errors reconnect without writing a spurious permanent gap, an idle
watch timer forces reconnects, and Run cancels sibling streams and recovers
from panics. Synthetic relist events carry a distinct event_id so unchanged
objects re-listed after a gap survive dedup.

Materialize: a baseline now resets object state (objects deleted during a gap
disappear) and heals open gaps; diff ignores server metadata by path, not by
key name, so user fields named status/uid are kept; nested add/remove carry
Added/Removed flags; dotted paths are escaped; Diff validates the window and
treats a zero before as empty; Snapshot records per-stream watermarks and
writes a TypeSnapshot journal record.

Replay: apply requires a successful dry run; gvrFor covers every policy kind
so Include* toggles work; unsupported kinds are reported as skipped instead
of silently dropped; NodePort services lose clusterIP and nodePort while
headless keeps clusterIP: None; targetNS is always honored; namespace mapping
collisions are detected; plan IDs and field managers are collision-safe and
plans are mutex-guarded against concurrent dry-runs/applies.

API: cursor pagination pushes ingest_seq into the SQL filter (export --server
no longer truncates); gap records expose their payload; /v1/diff requires a
cluster_id; dry-run/apply no longer accept a client-supplied kubeconfig;
plans carry target_context; HTTP server gets timeouts.

Metrics: the watch collector and replay planner now bump the registered
counters, and the server refreshes store-derived gauges on a ticker.

CLI: replay apply works locally and refuses to apply after a failed dry run;
coverage --server follows cursors and shows gap details; timeline
auto-detects namespaces and resolves cluster-scoped objects; diff validates
the window; export writes 0600 files; PVCs are no longer treated as
cluster-scoped; krply-server reports the build version.
2026-08-06 06:50:30 +05:30
c6d43a9d15
fix(replay): resolve cluster config through the standard chain
- fall back from in-cluster to KUBECONFIG and ~/.kube/config so a
  cluster-less host reports a clear error instead of a raw token path
- regression test for explicit kubeconfig loading
2026-08-06 06:09:24 +05:30
0baf78ddb7
feat(web): prefill demo defaults so views load instantly
- timeline picks the first cluster, stream, and a real observed object
- diff defaults to the first cluster and busiest namespace
- plans default to the first cluster, latest snapshot, and a source/target
  namespace pair, bootstrapping one plan when none exist
2026-08-06 06:06:02 +05:30
fbd7880d87
feat(server): seed demo journal from a bundled fixture
- --demo imports events and snapshot refs into an empty journal,
  idempotent across restarts, for public deployments without a cluster
2026-08-06 06:00:54 +05:30
994633da65
feat(web): default public ui to the render-hosted api
- krply.lverma.com and the vercel prod domain now query the
  krply-server backend on render instead of the static origin
2026-08-06 05:53:41 +05:30
9155ea248c
feat(api): add cors middleware with configurable origins
- wrap all routes with CORS, honoring KRPLY_CORS_ORIGINS (default *)
- short-circuit preflight OPTIONS and echo allowed origins
- honor the PORT env var for platform deployments (render etc)
2026-08-06 05:53:41 +05:30
6576672b1d
chore(web): ignore local vercel link metadata 2026-08-06 05:40:39 +05:30
2c2fe76984
ci: cancel superseded runs and deploy vercel only on web changes
- concurrency groups with cancel-in-progress for ci and vercel
- vercel workflow now triggers only when web/ or workflow files change
- renamed vercel project to krply-web for a stable production url
2026-08-06 05:39:16 +05:30
9418790598
ci: add github actions pipeline and vercel deployment
- go build, vet, unit/integration/e2e tests, and web build on push and pr
- vercel auto-deploy of the web ui, production on main and preview on prs
- requires VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID secrets
2026-08-06 05:34:04 +05:30
3eb2a2ffd4
test: add unit, integration, and e2e suites
- unit tests across storage, replay, and api layers
- integration suite driven by a fake apiserver (no cluster needed)
- end-to-end suite against a live cluster, tagged e2e
2026-08-06 05:34:04 +05:30
b04fd7a406
docs: add design and architecture documentation 2026-08-06 05:34:04 +05:30
22ba43a7ee
feat(deploy): add rbac, compose, and helm manifests 2026-08-06 05:33:59 +05:30
2e15d84dd6
feat(server): add query api, cli, metrics, audit, and web ui
- grpc query server for events, snapshots, diffs, and replay plans
- server metrics, request audit logging, and identity endpoint
- krply-server and krply cli entrypoints
- dependency-light dark web ui backed by the query api
2026-08-06 05:33:59 +05:30
21f6a56cb9
feat(replay): add sanitized replay planner and apply
- plan replay paths across the journal with irreversible-deletion and apply-order checks
- dry-run and live apply via list-and-watch with backoff
- produce human-readable path summaries for each resource
2026-08-06 05:33:59 +05:30
7cc863d40b
feat(core): add journal, collector, storage, and materializer
- durable event schema with stream identity and dedup hashing
- SQLite WAL and in-memory journal stores with atomic append+checkpoint
- list-and-watch collector with bookmarks, reconnects, and 410 relists
- state reduction, snapshots, and semantic field diffs
2026-08-06 05:30:51 +05:30