npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@knpkv/control-center

v0.8.1

Published

Human- and agent-oriented delivery control center

Readme

@knpkv/control-center

Control Center is a local, human- and agent-oriented delivery application. It connects release work across CodeCommit, CodePipeline, Jira, Confluence, and Clockify without allowing vendor models or server capabilities to leak into the browser.

This package is under active development, and its public API remains subject to change before 1.0.0.

Development

Node.js 26 or newer and the repository-pinned pnpm version are required.

pnpm --filter @knpkv/control-center dev
pnpm --filter @knpkv/control-center check
pnpm --filter @knpkv/control-center test
pnpm --filter @knpkv/control-center test:e2e

Development binds to 127.0.0.1:5173 by default. A LAN bind must opt into the security policy described below; a wildcard host alone is rejected.

For a deterministic CodeCommit review cycle, start pnpm mock:codecommit, then launch the server with the environment values it prints. The executable sends only CodeCommit and STS requests to the literal loopback endpoint. It uses fixed non-secret AWS fixture credentials and removes authorization and session-token headers before dispatch. The mock also supplies a temporary Git remote and an OpenAI-compatible review response, while Control Center still performs its normal clone, exact-head checks, sbx execution, output validation, and durable review transitions. Configured Atlassian, Clockify, CodePipeline, telemetry, and unselected AI providers keep their normal origins and credential boundaries. The admin API can advance PR 17, add an author reply, inspect request receipts, and reset the scenario. See packages/codecommit-mock/README.md.

CODECOMMIT_MOCK_GIT_REPOSITORY and CODECOMMIT_MOCK_GIT_REMOTE form one mock-only server configuration. Both require CODECOMMIT_MOCK_ENDPOINT; a partial pair or a non-file: remote fails startup. The repository name is the normalized provider identity already persisted in CodeCommit plugin and PR records and exposed only through authenticated API/browser surfaces; it is prohibited from unauthenticated and public diagnostics. The canonical file: URL is a server-private, non-persisted locator printed only to the operator terminal and prohibited from API responses, browser storage, application logs, and telemetry. CODECOMMIT_MOCK_ENDPOINT and CONTROL_CENTER_AGENT_OPENAI_API_URL are likewise non-persisted server-private locators, while CONTROL_CENTER_AGENT_OPENAI_MODEL is a non-secret identifier persisted with review jobs and exposed through authenticated review/provider APIs. The fixture must match the one enabled CodeCommit connection used by the review. A mismatch fails closed instead of falling back to AWS Git.

Release-cycle traceability

End-to-end release verification should carry the Jira work-item key in the branch name, commit subject, and pull-request title. Add a Changesets entry for the affected package, attach the Jira work item to its target fix version, and synchronize the configured Jira and source-control providers after the feature and Version pull requests merge. The Releases view can then verify the issue, pull request, and published delivery evidence as one connected release.

Distribution JavaScript budgets

validate:dist checks every emitted client and server .js file independently using its raw byte length and deterministic level-9 gzip byte length. Source maps, the Vite manifest, and build-graph.json are build metadata and are not runtime JavaScript artifacts.

| Target | Largest measured artifact | Measured raw / gzip | Per-artifact raw / gzip budget | | ------ | --------------------------- | ------------------------: | -----------------------------: | | Client | generated API client chunk | 270,002 / 80,249 bytes | 271,000 / 82,000 bytes | | Server | shared BindConfig-* chunk | 1,511,834 / 289,432 bytes | 1,650,000 / 292,000 bytes |

These initial ceilings were measured from a production build on 2026-07-19 and leave roughly four to six percent headroom, enough for build variance while rejecting meaningful per-file growth. The server chunk was about 6.87 MB raw and 1.09 MB gzip before the server build externalized declared runtime dependencies. Vite had followed linked workspace packages into their transitive graphs, including confluence-to-markdown's Atlaskit schema/transformer, AJV, Markdown, and ProseMirror dependencies, control-center-sql's query parser, and the broad codecommit-core root barrel. The server now keeps dependencies as runtime imports and uses narrow CodeCommit subpaths.

The client measurement was refreshed on 2026-08-29 after the managed-review API schemas and cleanup stage grew the generated client chunk to 270,002 raw bytes and 80,249 level-9 gzip bytes. Its ceilings are 271,000 raw and 82,000 gzip bytes; further growth still requires a new measurement and cause here.

The server measurement was refreshed on 2026-08-29 after native review cleanup classification added its runtime path to the shared chunk. It now measures 1,511,834 raw bytes and 289,432 level-9 gzip bytes; the 292,000-byte gzip ceiling keeps less than one percent headroom so further growth requires a new measurement and cause here. This shared chunk remains bounded technical debt: it is primarily Control Center's own application, persistence, plugin, API, and schema-snapshot graph. BindConfig is only Vite's generated chunk name, not the size owner. Future work should split that internal graph at deliberate runtime boundaries.

Run the application

Build once, then start the authenticated application server:

pnpm --filter @knpkv/control-center build
pnpm --filter @knpkv/control-center start

The first run prints a single-use pairing code and listens at http://127.0.0.1:4173. Durable data, content, and owner-only secrets live under .control-center by default; set CONTROL_CENTER_DATA_ROOT to choose another owner-controlled directory.

GET /.well-known/knpkv-control-center returns a versioned, credential-free identity used by the CodeCommit TUI before it opens the clean Open PR page. The probe is uncached and carries no workspace or session state.

A workspace owner or approver browser can open Open PR, paste a shared pull-request link, and resolve it through one narrow authenticated POST-body server-side batch resolver. Provider coordinates never enter the browser request target, history, or referrer. The AWS Console URL contains region, repository, and pull-request ID but no account identity. Control Center therefore opens an exact unique match, reports an unsynchronized PR, or asks the operator to choose among browser-safe AWS account labels; it never guesses. A truncated candidate prefix or missing account identity fails closed.

Real Atlassian OAuth acceptance journey

The full interactive Jira + Confluence OAuth journey is opt-in because it requires a human Atlassian consent and access to a real site. Register the callback URL http://127.0.0.1:<temporary-port>/services/oauth/atlassian/callback in the OAuth app, then run:

CONTROL_CENTER_TEST_ATLASSIAN_OAUTH=1 \
CONTROL_CENTER_TEST_ATLASSIAN_PORT=4173 \
CONTROL_CENTER_TEST_ATLASSIAN_CLIENT_ID=... \
CONTROL_CENTER_TEST_ATLASSIAN_CLIENT_SECRET=... \
CONTROL_CENTER_TEST_ATLASSIAN_PROJECT_ID=... \
CONTROL_CENTER_TEST_ATLASSIAN_SPACE_ID=... \
CONTROL_CENTER_TEST_ATLASSIAN_PAGE_ID=... \
CONTROL_CENTER_TEST_ATLASSIAN_EXPECTED_ACCOUNT_EMAIL=... \
CONTROL_CENTER_TEST_ATLASSIAN_EXPECTED_SITE_URL=https://example.atlassian.net/ \
pnpm --filter @knpkv/control-center test:e2e:atlassian-oauth

The command starts a fresh temporary server and data root on the configured fixed port, pairs through the browser, waits for the operator to complete Atlassian sign-in and consent, selects one site, creates both provider connections, and runs both connection checks. Register the callback using the same port before starting the command. The client secret is used only as masked form input; the test disables screenshots and traces, verifies the canonical profile contains credentials, and checks browser storage, SQL/WAL/journal files, Playwright artifacts, and server output for the client/provider credentials. It removes the temporary data, auth, and configuration roots on success or failure. Provider tokens remain server-private and are never returned to browser storage or SQL.

Local OpenTelemetry

Control Center can export Effect traces and structured logs to an OTLP/HTTP collector. Export is opt-in and disabled unless the corresponding OpenTelemetry exporters are enabled. Metrics are not exported in this initial slice.

For example, start motel, then run Control Center against its default local listener:

OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:27686 \
OTEL_EXPORTER_OTLP_PROTOCOL=http/json \
OTEL_LOGS_EXPORTER=otlp \
OTEL_TRACES_EXPORTER=otlp \
pnpm --filter @knpkv/control-center start

To use Lensflare, create or select a dataset in its local UI and substitute that dataset's slug below. Lensflare listens on port 43110 by default and uses dataset-specific ingest routes:

OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=http://127.0.0.1:43110/ingest/otlp/v1/logs/<dataset-slug> \
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://127.0.0.1:43110/ingest/otlp/v1/traces/<dataset-slug> \
OTEL_EXPORTER_OTLP_PROTOCOL=http/json \
OTEL_LOGS_EXPORTER=otlp \
OTEL_TRACES_EXPORTER=otlp \
pnpm --filter @knpkv/control-center start

Lensflare's optional MCP endpoint for querying the captured telemetry is http://127.0.0.1:43110/mcp; it is separate from the ingest endpoints above.

When an exporter is enabled without an endpoint, Control Center uses the OpenTelemetry defaults: http://localhost:4318, /v1/logs and /v1/traces, with http/protobuf. Set OTEL_EXPORTER_OTLP_PROTOCOL=http/json for JSON-only collectors, or use the standard signal-specific protocol variables when the two signals differ. OTEL_SERVICE_NAME may override the default control-center service name, while the standard signal-specific endpoint and header variables can target another compatible collector. Exporters flush their bounded batches when the scoped Control Center runtime shuts down; collector outages do not fail application work.

SIGINT and SIGTERM begin graceful drain before scoped runtime resources close. The server rejects new authenticated mutations and live-event streams with a retryable 503, closes existing live-event streams, and gives already-admitted mutations or startup background jobs up to ten seconds to finish. Release-chat and PR-review workers, workspace retention, release synchronization, governed-action recovery, and Atlassian OAuth grant timers all share this full-work admission barrier. Worker claims remain recoverable through their durable leases, and stale PR-review sandboxes are reconciled before new review work starts. After admitted work and existing streams clear, one stable snapshot of named subsystem hooks runs sequentially. The governed worker appends immutable shutdown expirations for its still-live recovery claims so another process can reclaim them immediately; then the local SQLite hook checkpoints and truncates the WAL. Hook defects are reported by secret-free hook identity, and the hard deadline still bounds the complete work-and-flush sequence. Mutation-only callers retain a separate barrier that does not wait for startup background jobs or flush hooks.

Fake release synchronization records an immutable attempt before acquiring its provider and appends a completion only after the synchronized page boundary is durable. Startup first reconciles every still-open attempt for the configured fake-provider stream as interrupted, using the stream's current durable revision and exact committed-page delta, then admits the next attempt. A provider outage completes as source-unavailable; cancellation, defects, and persistence failures never become successful synchronization records.

When the private governed worker is enabled, startup selects at most 64 actions from the configured bootstrap workspace whose recovery safety interval has elapsed. The effect-qb query uses stable lease/workspace/action order and excludes unexpired, un-released recovery claims. Each candidate enters the existing inspect-and-reconcile path sequentially, so startup never redispatches an ambiguous provider mutation. A candidate-list failure prevents the worker from becoming ready; individual typed failures and defects are counted in the secret-free startup summary while the remaining bounded batch continues. Runtime interruption still stops the sweep, and an explicitly expired claim rejects late provider outcomes while allowing immediate deterministic takeover.

Local release agent

Every canonical release page has a release-owned Relay thread. An owner browser sends its bounded prompt and recent thread history through the typed API; the server resolves the current workspace-scoped release projection before each turn and runs the selected local CLI with read-only filesystem access. Provider configuration, credentials, filesystem paths, and raw provider failures remain server-only. Threads are isolated by browser session and currently remain in that tab; provider session identifiers are not treated as durable product state.

Local providers are disabled by default. Enabling one grants that CLI read access to the configured working directory, so use an owner-controlled, least-privilege checkout and trusted HTTPS:

CONTROL_CENTER_AGENT_PROVIDERS=codex,claude \
CONTROL_CENTER_AGENT_CWD=/srv/workspaces/payments \
pnpm --filter @knpkv/control-center start

# Keep local agents disabled while leaving the release UI available.
pnpm --filter @knpkv/control-center start

CONTROL_CENTER_AGENT_CWD is required whenever a provider is enabled; Control Center does not silently grant access to its launch directory.

CONTROL_CENTER_AGENT_CODEX_EXECUTABLE, CONTROL_CENTER_AGENT_CODEX_MODEL, CONTROL_CENTER_AGENT_CLAUDE_EXECUTABLE, and CONTROL_CENTER_AGENT_CLAUDE_MODEL provide server-only overrides. The respective CLI must already be installed and authenticated for the operating-system user running Control Center. Agent turns have a separate low-rate budget and a 130-second request deadline; each adapter applies a two-minute subprocess deadline and bounded output capture inside that request.

An OpenAI-compatible chat-completions endpoint can be registered independently:

CONTROL_CENTER_AGENT_OPENAI_API_URL=https://provider.example/v1 \
CONTROL_CENTER_AGENT_OPENAI_MODEL=review-model \
CONTROL_CENTER_AGENT_OPENAI_API_KEY=server-only-token \
pnpm --filter @knpkv/control-center start

The API key is optional for trusted local endpoints. Provider credentials, API URLs, executable paths, working directories, provider-native values, and raw failures stay behind the server registry. The owner-only GET /api/v1/agent/providers response exposes only provider identity, configured model identifiers, and available / not-configured health. The enqueue contract accepts only the fixed read-only safe profile. OpenAI-compatible generation has an interruptible two-minute deadline; tests may inject a shorter deadline without using host timers.

The release thread exposes explicit Run with Codex and Run with Claude presets plus bounded release prompt templates. The selected provider is sent with every turn; Control Center never silently substitutes another local runner.

Immutable CodeCommit review execution is a separate opt-in worker. It supports the authenticated Codex or Claude CLI running natively in its matching agent sandbox, or an OpenAI-compatible Effect AI model using the typed shell-sandbox toolkit. All modes require the sbx CLI, git, the AWS CLI credential helper, and an enabled CodeCommit connection whose repository matches the review subject.

Native Codex review:

CONTROL_CENTER_AGENT_PROVIDERS=codex \
CONTROL_CENTER_AGENT_CWD=/srv/workspaces/payments \
CONTROL_CENTER_PR_REVIEW_SBX_ENABLED=true \
CONTROL_CENTER_PR_REVIEW_SBX_EXECUTABLE=sbx \
CONTROL_CENTER_PR_REVIEW_CODEX_EXECUTABLE=codex \
pnpm --filter @knpkv/control-center start

Native Claude review:

CONTROL_CENTER_AGENT_PROVIDERS=claude \
CONTROL_CENTER_AGENT_CWD=/srv/workspaces/payments \
CONTROL_CENTER_PR_REVIEW_SBX_ENABLED=true \
CONTROL_CENTER_PR_REVIEW_SBX_EXECUTABLE=sbx \
CONTROL_CENTER_PR_REVIEW_CLAUDE_EXECUTABLE=claude \
pnpm --filter @knpkv/control-center start

To offer both review presets, configure CONTROL_CENTER_AGENT_PROVIDERS=codex,claude and authenticate both CLIs. The review launch dialog then offers Codex review and Claude review without changing the immutable head. Correctness, Security, and Tests templates populate the targeted-review request and remain editable before enqueue.

OpenAI-compatible typed-tool review:

CONTROL_CENTER_AGENT_OPENAI_API_URL=http://127.0.0.1:11434/v1 \
CONTROL_CENTER_AGENT_OPENAI_MODEL=review-model \
CONTROL_CENTER_PR_REVIEW_SBX_ENABLED=true \
CONTROL_CENTER_PR_REVIEW_SBX_EXECUTABLE=sbx \
CONTROL_CENTER_PR_REVIEW_SBX_TEMPLATE=review-template \
pnpm --filter @knpkv/control-center start

When CONTROL_CENTER_PR_REVIEW_SBX_ENABLED is false or absent, the worker is disabled and no provider advertises pr-review. Enabling it without Codex, Claude, or an OpenAI-compatible provider fails startup. CONTROL_CENTER_PR_REVIEW_SBX_EXECUTABLE defaults to sbx; the optional template applies to the typed shell-sandbox path. CONTROL_CENTER_PR_REVIEW_CODEX_EXECUTABLE and CONTROL_CENTER_PR_REVIEW_CLAUDE_EXECUTABLE default to codex and claude and name the executable inside the corresponding agent sandbox; the host-only CONTROL_CENTER_AGENT_*_EXECUTABLE settings do not cross that boundary. Ambient provider credential environment variables are never forwarded into the review sandbox; authentication is owned by the selected sbx run codex or sbx run claude connection. For each durable claim the worker resolves exactly one enabled CodeCommit connection, clones the exact head into a private data-root workspace, and hands that checkout to one named sbx sandbox. It strips Git remotes and credential helpers and verifies the full head object ID before review. With the loopback mock configured, the same resolver accepts only the normalized repository identity configured by CODECOMMIT_MOCK_GIT_REPOSITORY and clones its server-private canonical file: URL. Other repositories fail closed. The typed-tool path denies all sandbox network access. Native CLI review instead enables only the selected provider connection, disables session persistence and unrelated MCP configuration, and uses only the disposable clone. Codex retains the sbx-owned user configuration required for its credential proxy while disabling project-document and exec-policy loading from the reviewed head; Claude disables project, local, and user setting sources so its CLAUDE.md files are review content rather than executable instructions, and safe mode disables automatic project-memory discovery. Every path validates structured output and exact diff evidence on the trusted host. Sandbox names use a server-private compact workspace-scoped prefix and remain within sbx's 63-character limit, and begin with the configured worker workspace's cc-pr-review-<compact-workspace-id>- prefix. Startup retains live names in that owned namespace for recovery inspection and never removes foreign-workspace or legacy unscoped names automatically. When no owned live sandbox remains, active review jobs receive a durable interrupted result with partial evidence and a later operator retry creates a new immutable run. While a review is running, the worker renews its durable lease and observes cancellation; cancellation interrupts the scoped checkout, sandbox, and model work before durably completing the job as cancelled. CONTROL_CENTER_PR_REVIEW_BUDGET_MILLIS and CONTROL_CENTER_PR_REVIEW_MAXIMUM_DURATION_MILLIS default to 1,200,000 and 3,600,000 milliseconds, respectively. The maximum session duration should be at least the selected Review Agent Profile budget. The worker enforces the selected budget independently of provider process limits. An operator may extend one running review once by one profile budget; the extension is durable and visible to the worker after restart. Cancellation and budget expiry retain the last validated partial report, mark the run unable to conclude, and leave any retained suggestions as advice-only because unexplored project areas remain.

Provider parity is enforced at the Review Sandbox boundary: native Codex and Claude receive the same immutable checkout, bounded review prompt, structured report schema, exact diff anchoring, activity, and cleanup contract. The deterministic executor tests exercise that shared request shape for both providers; the installed-runtime fixture additionally runs full-project discovery, a command, a write, diff generation, and a structured JSON result without credentials. Run that fixture deliberately with pnpm --filter @knpkv/control-center test:sbx:real; it requires Docker and sbx, but does not require AWS, Codex, Claude, or provider API credentials. The real authenticated Codex CLI smoke remains an explicit separate opt-in in @knpkv/ai-codex.

The launch dialog shows the exact head, selected Review Agent Profile, budget, network policy, and sbx runtime before enqueue. The selected model explores the complete project inside the Review Sandbox. Failures retain a redacted stage and cause, such as source checkout, sandbox startup, provider authentication, rate limiting, command timeout, or result validation. The browser uses those stable values for specific recovery guidance without receiving stderr, credentials, provider payloads, or workspace paths. Release-chat CLI selection first reads a bounded, credential-free --version response and fails closed when the configured host executable cannot identify itself. Native review selection is independent of that host executable because its CLI lives inside the matching sbx agent image. Safe runtime metadata, when available, is retained with the run-started event and shown in the Review Thread; executable paths and inherited credentials are excluded. Only schema-valid suggestions whose path, range, and excerpt match immutable diff evidence are retained; line suggestions use added lines, while file suggestions may use deleted base-side lines for deletion-only changes. Investigation remains live activity. A suggestion has one host-resolved line, file, or whole-change anchor, with repeated occurrences grouped as Related Locations. File anchors use the first added line and fall back to line 1. Exact-head Suggested Replacements remain inert unified diffs and must pass git apply --check against the sandboxed head, while recurring high-impact prevention proposals stay visibly separate for later review. Low-confidence and pre-existing concerns appear as non-publishable Review Notes.

Each retained suggestion has an immutable local revision history. The original agent result is revision 1; saving an edit appends a complete new snapshot instead of rewriting the report or prior evidence. The inline card shows the current revision, validation state, author, and time. History keeps prior snapshots in the diff workspace, while Edit opens a schema-checked complete editor. Concurrent saves use the expected revision and surface a conflict without discarding the local draft. A title-only edit retains its validation. Changes to severity, claims, evidence, confidence, anchor, related locations, replacement, or prevention are marked Needs revalidation and cannot be published.

The diff workspace keeps the complete file inventory visible while severity and state filters narrow only the review advice. Line suggestions render inline; file and whole-change suggestions use the compact overview. When the provider returns Review Orientation, the workspace first explains the overall change as ordered Change Cohorts and Change Layers. Layers use the stable contract, data-flow, implementation, callers, tests, docs-release order. Each layer survives only when all displayed ranges resolve to concrete added lines in the immutable provider diff. Control Center derives Changes Required, Non-blocking Suggestions, No Issues Found, or Unable to Conclude from the validated report. The model does not author that outcome, and there is no suggestion-count cap beyond the existing durable event byte envelope.

The Review Thread shows input and output token totals for the selected durable run. Provider/model and cost fields that were not reported remain visibly Not reported. When a synchronized head differs from the last reviewed head, the workspace names both revisions, blocks old findings from publication, and offers an explicit Review current head action.

Every current, validated draft suggestion can be explicitly published. Preview, governed evidence, reservation, provider receipt, and the Review Thread event all bind to the exact suggestion revision; an edit cannot reuse an older preview or publication reservation. Line and file suggestions become CodeCommit comments at their resolved line; whole-change suggestions become general pull-request comments without a file location. Control Center first reserves the exact confirmed content digest so competing edits cannot both reach the provider. Each attempt owns its reservation with a unique durable identifier. Live same-content joiners remain in progress; a null-handle reservation may be atomically taken over after ten minutes, while the stale owner remains unable to release or complete it. The successor re-enters the governed idempotent publication path, which prevents a second provider write when the first attempt's outcome was ambiguous. A successful governed publication completes that reservation and appends an immutable lifecycle event, so reopening or refreshing the review keeps that suggestion published and cannot offer it as a new draft again. Confirmed provider no-write outcomes release the reservation for an edited retry. Multi-region replacement previews keep explicit file/hunk boundaries, and provider output reserves durable-envelope space for host-added review metadata. Completed same-content retries replay the durable governed receipt without another provider call, and deletion-only file anchors retain their base-side CodeCommit position. Compensating reservation cleanup is best-effort and never masks the provider result returned to the operator.

To exercise the installed sbx runtime against the current checkout without provider credentials or remote writes, run:

pnpm --filter @knpkv/control-center test:sbx:real

The opt-in smoke creates a private clone, denies its network, verifies its exact revision, proves the clone is writable, and removes the sandbox on exit. The default test suite keeps using deterministic process doubles.

Durable enqueue requests must explicitly select the provider, one catalog model, and the read-only profile. The selection is validated fail-closed before enqueue and persisted in the existing job provider_id, model, and access fields. The provider receives a bounded frozen projection containing the release identity, service, version, lifecycle, freshness, collaborators, and other safe release facts; the replay stream retains the original user question. Legacy jobs with no persisted model resolve to the single configured catalog model at the registry boundary. A workspace-wide default is deliberately deferred to the revision-protected settings work in M5.2; there is no M4.3 schema migration.

If the first code was lost after the workspace initialized, or no owner session remains, stop the server and run terminal recovery against the same data root:

pnpm --filter @knpkv/control-center start recover-owner

Recovery verifies the owner and mode of the canonical data directory, then requires the exact terminal phrase ISSUE OWNER RECOVERY CODE. A successful recovery revokes existing owner sessions and every outstanding pairing code before it prints a replacement single-use code. It is deliberately unavailable over HTTP.

Offline backup and restore

Stop Control Center and every other process that can write its data root before creating or restoring a backup. The workspace commands below pass the same arguments as the installed control-center binary:

CONTROL_CENTER_DATA_ROOT=/srv/control-center \
pnpm --filter @knpkv/control-center start backup /srv/control-center-backups/2026-07-14

pnpm --filter @knpkv/control-center start verify-backup /srv/control-center-backups/2026-07-14

CONTROL_CENTER_DATA_ROOT=/srv/control-center-restored \
pnpm --filter @knpkv/control-center start restore /srv/control-center-backups/2026-07-14

backup <archive> treats CONTROL_CENTER_DATA_ROOT as its source. That source must already be a prepared Control Center data root, and its writers must remain stopped for the whole command. Backup does not create, adopt, repair, or migrate the source. The archive pathname must not already exist and must not contain or be contained by the source; publication fails rather than replacing caller-owned data.

verify-backup <archive> reads and verifies only the archive. It does not read CONTROL_CENTER_DATA_ROOT, even when that variable is set, and it does not modify the archive.

restore <archive> treats CONTROL_CENTER_DATA_ROOT as its destination. The configured destination must not exist, including as a dangling symlink, and it must not contain or be contained by the archive. Restore verifies the archive before creating the destination and publishes the restored data root without overwriting an existing or concurrently created target. A later normal control-center start requires the restored database to match the current unstable schema exactly.

Each successful offline command writes exactly one summary line to standard output and nothing to standard error: Backup created., Backup verified., or Backup restored. A valid archive with unavailable reproducible cache content remains usable and instead reports Backup created with N reproducible cache gaps., Backup verified with N reproducible cache gaps., or Backup restored with N reproducible cache gaps. Usage and command failures write only to standard error and exit nonzero; command failures use the stable Control Center command failed (<ErrorTag>). form without exposing storage paths or secret values.

Retention and startup integrity

Normal startup verifies SQLite's integrity, required pragmas, and the exact unstable schema before exposing persistence. It never repairs, resets, or migrates a damaged database automatically; restore a verified offline backup when integrity fails.

For an explicitly bootstrapped workspace, startup applies one bounded pass of the governed retention settings and repeats it daily under the graceful-drain lifecycle. Replay retention advances the durable pruned cursor while removing only old domain-event projection rows. Content retention removes reproducible diff-cache mappings through the existing durable cleanup-intent protocol. Evidence retention requires expiry, no legal hold, and no authoritative references. Agent retention requires terminal, unpublished, unreferenced work and deletes its private dependent history in one transaction. Canonical governed-action, settings, export, and cleanup audit records remain immutable.

Every committed pass appends an immutable summary with the exact workspace, retention class, settings policy revision, cutoff, batch limit, selected count, deleted count, and completion time. Evidence, agent, and Review Sandbox artifact deletion triggers accept only exact transient claims belonging to that cleanup transaction. PR-review startup records successful stale-sandbox reconciliation in the same bounded audit stream. Large command output is stored as an immutable, expiring artifact scoped to its workspace, thread, job attempt, command sequence, and stream; bounded secret-free metadata discovery plus exact-handle page/search reads survive worker recovery, while redacted metadata contains no command text or output. Raw reads fail at the declared expiry even before physical cleanup runs. Each command’s retained stdout and stderr commit atomically, each attempt is capped at 64 artifacts and 64 MiB, each artifact is capped at 16 MiB, and expiry never cascades into semantic review history.

The Vite development server stays loopback-only and is not the production application server. A new remote browser must pair over trusted HTTPS. The simplest supported setup keeps Control Center on loopback and puts a TLS reverse proxy on the same machine. Configure the proxy to serve a hostname and certificate trusted by the second machine, forward to http://127.0.0.1:4173, and overwrite X-Forwarded-Host, X-Forwarded-Proto, and X-Forwarded-For. X-Forwarded-For must contain exactly the browser's IP literal: do not append a chain or forward the incoming header. Then start Control Center with the proxy's exact address:

proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-For $remote_addr;
CONTROL_CENTER_HOST=127.0.0.1 \
CONTROL_CENTER_PORT=4173 \
CONTROL_CENTER_PUBLIC_ORIGIN=https://control.home.arpa \
CONTROL_CENTER_ALLOWED_HOSTS=control.home.arpa \
CONTROL_CENTER_ALLOWED_ORIGINS=https://control.home.arpa \
CONTROL_CENTER_TRUSTED_PROXY_ADDRESSES=127.0.0.1 \
pnpm --filter @knpkv/control-center start

Open https://control.home.arpa from the second machine and enter the one-time code printed by the server. Replace the example hostname with one that resolves to the server on both machines. If the local proxy connects over IPv6, trust its exact ::1 address instead of 127.0.0.1. Never add client addresses or a subnet: forwarded headers are accepted only from the exact immediate proxy. Malformed, chained, or spoofed client-address headers fall back to the immediate peer for rate limiting.

Direct TLS is also available when certificate and private-key material has already been provisioned into this instance's SecretStore; pass the resulting opaque references as CONTROL_CENTER_TLS_CERTIFICATE_REF and CONTROL_CENTER_TLS_PRIVATE_KEY_REF. The application never accepts certificate paths or key bytes through environment variables.

CONTROL_CENTER_ALLOW_INSECURE_LAN=true is a deliberately restricted viewing mode, not remote onboarding. It blocks pairing, session administration, local agent execution, provider configuration, policy changes, and secret inspection. A new browser therefore cannot establish its required HttpOnly session in that mode; use trusted HTTPS for normal remote access.

Release gates

Run the complete package gate with:

pnpm --filter @knpkv/control-center test:e2e
pnpm --filter @knpkv/control-center benchmark:contracts
pnpm --filter @knpkv/control-center benchmark:validate-runtime

test:e2e builds Control Center through its manifest-based workspace artifact repair, removes any prior runtime report, and runs the production-route browser suite with one Chromium worker. The suite covers public and authenticated route families under keyboard navigation, automated WCAG 2.2 AA checks, a 320 CSS-pixel viewport, forced colors, and reduced motion. It also exercises pairing from a simulated second machine through a test-only HTTPS reverse proxy that overwrites the forwarded host, protocol, and client address.

The deterministic fixture contains exactly 100 releases, 2,000 entities, 10,000 relationships/evidence records, 500 files, 20,000 timeline events, and a bounded 500-event SSE replay. The browser suite writes test-results/control-center/runtime-benchmark.json; validation rejects missing, pruned, contradictory, or incorrect cardinality, ordering, resource-lifecycle, and timing evidence.

Absolute timing is an acceptance assertion only on Linux x64 or arm64 with Node 26 or newer, at least four logical CPUs, at least 8 GiB RAM, and an explicit CONTROL_CENTER_BENCHMARK_STORAGE_CLASS=local-ssd declaration. On that class, the warmed authenticated portfolio HTTP p95 must be at most 2,000 ms. Other machines still execute every fixture, correctness, bound, SSE-ordering, and cleanup assertion, but the report must identify timing as informational. The storage class defaults to unverified; the benchmark never infers one from an operating-system or filesystem label.

For a standalone run that builds once, measures the browser runtime, and validates its report, use:

pnpm --filter @knpkv/control-center benchmark

Public entries

  • @knpkv/control-center — browser-safe API and domain contracts
  • @knpkv/control-center/api — shared typed API contracts
  • @knpkv/control-center/domain — Schema-backed vendor-neutral domain contracts, including canonical IDs, people and agent roles, source freshness, and deterministic release identity
  • @knpkv/control-center/server — server composition

The browser application is intentionally private. It consumes @knpkv/rly, while the root, API, domain, and server boundaries are mechanically prevented from importing the design system. Server composition is available only from the explicit /server entry. Production code is also forbidden from importing the approved prototype at runtime.

Release Relay projections are domain data, not presentation state. Each release persists its relay/v1 codename and three-symbol projection; readers validate that projection against the canonical release ID so a future relay algorithm can be introduced without silently changing existing release identity.

Plugin contract

The version-one plugin contract is vendor-neutral and capability-negotiated. Descriptors use structured semantic versions and secret-free configuration metadata; each read, sync, diff, proposal, execution, cancellation, and reconciliation capability negotiates its own integer version. Unsupported contract majors, malformed descriptors, and unsupported required capabilities are rejected before an adapter factory runs.

Adapters emit bounded pages of Schema-decoded UpsertEntity, TombstoneEntity, AppendEvidence, UpsertPerson, and ProposeRelationship events. They cannot choose workspace or connection scope. Canonical descriptor JSON is capped at 60 KiB, normalized attributes, evidence, and governed-action payloads at 256 KiB, and each complete encoded sync page at 1 MiB; adapter transports enforce limits before buffering provider responses. Diff paths are normalized provider-relative paths, and decoded content ranges are valid base64 capped at 1 MiB and at the requested range. A decoded page and its next checkpoint commit in one transaction; replay uses stable event and page identities, malformed pages enter redacted quarantine, and failures never replace the last valid cache.

The exported PluginConnection service contains reads, health, sync, complete-diff access, and governed-action proposals only. Every proposal carries its canonical payload digest, and authorization must preserve that digest. Adapters implement a tag-free executor shape; plugin composition seals it behind a non-exported live service that only the governed-action engine may obtain. Source-boundary validation prevents adapters, browser code, and agent code from importing that authority. Safe reads and explicitly idempotent writes use at most three attempts with capped full jitter and decoded Retry-After; a stream is retried only before its first emitted page, and excessive Retry-After values fail instead of retaining a fiber. Unsafe or ambiguous mutations are reconciled rather than replayed.

CodeCommit read adapter

The production CodeCommit adapter exports an opaque CodeCommitPluginDefinition from @knpkv/control-center/server. One connection configures an AWS profile, region, and repository name. It negotiates entity.read@1, sync.incremental@1, diff.inventory@2, and diff.content@2 (while retaining the v1 codecs for persisted descriptors), then normalizes pull requests with immutable PR/base/head revisions and complete cursor-based changed-file pages. Its governed review actions support exact-head create, update, and reply comment mutations plus native approval state changes; every mutation remains behind the human-confirmed action flow. Diff v2 requires the synchronized provider revision and immutable base/head commits; the authenticated application resolves those coordinates from the workspace-scoped canonical projection rather than accepting them from the browser. Provider output is decoded by @knpkv/codecommit-core before it enters the vendor-neutral plugin contract; raw AWS types and causes do not cross the adapter.

Authenticated diff APIs collect at most 500 files and 100 provider pages before returning ready; partial inventories never masquerade as complete. Every file receives a stable exact-revision anchor. Content reads resubmit that anchor with the normalized status and previous path in a bounded read-only POST payload, keeping maximum-length rename identities out of the request URL. The application verifies the canonical identity before the provider selects the exact entry from the stored commits, so synchronized historical revisions remain readable after the live pull request advances. Text content is fetched only for the selected before/after side in ranges of at most one MiB. Binary, generated, oversized, and missing content remain explicit inventory/workbench states; authentication, throttling, timeout, and provider outages remain typed failures and retain the normal safe-read retry policy.

This milestone's synchronized entity data remains read-only and does not expose comment reads, commits/history, checks, or merge. Only the governed create, update, and reply comment mutations and approval actions described above are exposed; no ungoverned provider mutation capability exists. Provider credentials and AWS response types stay behind the scoped server runtime and never enter browser state or diff URLs.

AWS CodePipeline adapter

The server entry exports an opaque production CodePipeline plugin definition for one configured AWS profile, region, and pipeline. Alongside entity.read and sync.incremental, it negotiates bounded pipeline.logs and pipeline.artifact evidence reads plus governed action proposal, execution, and reconciliation. Direct @distilled.cloud/aws CodePipeline, CloudWatch Logs, S3, and STS calls remain behind an injectable provider service; repository-owned Schemas decode every returned account, pipeline, execution, action, log page, and artifact range before it can become plugin data. Credential, authorization, throttling, timeout, malformed-response, outage, and not-found outcomes remain typed and redacted.

Start requests pin explicit source revisions and use a deterministic AWS client request token. Stop and manual approval revalidate the exact pipeline definition plus execution or action revision immediately before mutation; provider reason/summary limits are enforced before authorization, and approval tokens remain inside the provider boundary. Retry starts a distinct execution at the failed execution's captured source revisions, records the original execution as retryOf, and uses the same deterministic token on reconciliation. Non-null reconciliation locators are decoded and bound to the authorized kind and payload digest before provider access. The authenticated workspace-scoped evidence proxy reloads the selected action before every read. Log cursors are opaque and bounded, including a private intra-page offset for lossless byte-bounded pagination; artifact responses expose only attachment bytes with private/no-store and nosniff policy, never S3 coordinates, log ARNs, signed URLs, or credentials.

Each execution provider page contains at most one execution, allowing its pipeline, execution, stage, and action events to fit one atomic plugin page and checkpoint. One synchronization invocation reads at most 20 execution pages. Action history requests at most 100 records per page, five pages, and 200 actions per execution; a truncated read is labeled instead of pretending to be complete. Discovery and execution snapshots use at most two concurrent provider calls. Provider cursors are opaque, replayable checkpoints, and repeated action cursors or mismatched identities fail closed.

Normalized events carry the pipeline ARN, region, provider update/sample time, immutable execution/action identities, status, operator provenance, source revisions, and bounded stage/action summaries. Server-private artifact references retain S3 bucket/key coordinates only long enough to resolve authenticated proxy reads; normalized artifact metadata exposes only names and proxy-required access markers. Resolved action configuration, provider artifact URLs, revision URLs, and external execution URLs are never exposed. Governed start, stop, manual approval, and retry operations are sealed behind the authorized executor, while log and artifact contents remain available only through the authenticated workspace-scoped proxy.

The canonical CodePipeline entity page is a read-first execution flight recorder. It correlates the already bounded pipeline, stage, and action events from one accepted provider page, preserves configured stage order, and shows execution identity, trigger and revision, derived deployment target, duration, operator and approval identities, action outcomes, and current release/PR/runbook evidence. The canonical projection deliberately removes S3 bucket/key coordinates and log ARNs: browser-visible artifacts retain only their name, direction, and proxy-required access state. Truncated stage or action reads remain explicitly labeled and are never presented as complete.

Jira issue adapter

makeJiraReadPluginRuntime from @knpkv/control-center/server builds the production Jira adapter around the shared Schema-validated JiraApiClient. It negotiates bounded project synchronization, entity.read for jira.issue, revision-inspected governed proposals for comments, reply fallbacks, exact fix-version assignments, and typed issue links, plus a separately governed create-release-version action. Every issue proposal preserves the exact jira.issue target identity and records the inspected issue revision. Jira issue provider writes remain disabled until Jira offers a documented, verified provider-enforced atomic revision precondition for the exact target revision; append-only authorization is not a substitute for that guard. The release-version action is create-only and project-scoped: it never edits an existing issue or version, checks for an exact existing name before dispatch, and reconciles ambiguous outcomes by that name. Its durable canonical request is the governed-action envelope_json: the payload persists only projectId, exact name, and release description; the production identity also binds the workspace, selected connection and its verified Atlassian site, release, source-revision digest, immutable project destination, and canonical payload digest. Provider credentials remain server-private and are never durable payload fields.

The secret-free runtime configuration requires an HTTPS Jira Cloud tenant root webBaseUrl under atlassian.net, its stable Atlassian cloud siteId, the immutable projectId followed by this connection, an activity pageSize from 1 to 50, a maximumPages limit from 1 to 5, and a per-request operationTimeoutMillis from 1,000 to 120,000. Discovery verifies the project through Jira before it can become a followed resource, and entity reads fail closed when an issue belongs to another project. Authentication remains in the externally supplied JiraApiClient layer, so tokens never enter plugin configuration.

OAuth profiles provide the verified cloud ID used to share one Atlassian site across Jira and Confluence. Jira API-token connections remain usable but standalone because the scoped Jira REST surface does not prove that cloud ID; adding a Jira project from an existing site card therefore requires a matching OAuth profile. Confluence trusts the already-validated OAuth profile identity and verifies API-token setup through its system-information response. Pre-stability Jira descriptor generations without both siteId and projectId enter an explicit plugin-configuration-migration-required state; recreate those local connections while migrations are intentionally disabled.

An issue read fetches the issue, comments, and changelog through interruptible Effect operations. Pagination stops at the configured bound and records explicit comment/history truncation flags. The normalized issue attributes include description and environment text, workflow metadata, release versions, parent and subtasks, comments, history, and deduplicated collaborators with roles and avatar URLs. If fixed issue fields would cross the payload cap, optional arrays and presentation fields are omitted deterministically and named in truncatedFields. OpenAPI, HTTP, timeout, authentication, authorization, rate-limit, outage, and adapter-schema failures are translated to the closed plugin failure taxonomy without retaining raw provider causes.

The issue-targeted proposals are useful for review and authorization workflows, but this adapter does not execute or reconcile them. Jira Cloud's issue-comment API does not expose portable threaded replies, so a reply proposal is rendered as a normal comment headed with the inspected parent comment ID; a missing parent blocks the proposal. Issue-link proposals require an explicit direction and retain Jira's canonical inward and outward labels: outward means the target issue points to the linked issue, while inward means the linked issue points to the target issue. Workflow transitions and description replacement remain unsupported, and all comment, fix-version, and issue-link provider mutations stay disabled behind the proposal boundary. Separately, Relay can execute and reconcile create-only Jira project-version publication after an explicit workspace-owner confirmation.

Confluence page adapter

The production Confluence adapter negotiates entity.read@1, bounded sync.incremental@1 for the pages stream, and governed action.propose@1, action.execute@1, and action.reconcile@1 page publication. Each connection is pinned to one immutable space ID under its verified Atlassian site. Space iteration and actions always send that exact ID to Confluence and reject any returned page belonging to another space, so followed spaces sharing one OAuth site remain isolated.

Synchronization retains current page and bounded revision metadata, owner/author/contributor/watcher roles, safely converted current page text, and at most two pages each of watcher and attachment metadata without loading attachment bytes. When the normalized payload would exceed its bound, content is dropped first and explicitly remains contentState: "lazy"; entity.read can still load and safely convert the exact page. Titles containing operational runbook terms emit explicit confluence.runbook-candidate evidence rather than silently classifying a page as authoritative documentation.

One invocation reads at most five provider pages and persists a resumable bounded:<cursor> checkpoint when more work exists. Large provider pages are deterministically divided into contract-sized atomic pages. Intermediate chunks use a restart checkpoint for the current provider page so interruption replays stable event identities instead of skipping uncommitted entities.

An update-page proposal accepts bounded Markdown, converts it through the owning package's strict outgoing ADF validator, and freezes the canonical ADF, title, space, expected version, and exact next version in the authorized payload. Final preflight blocks a changed revision or a visible unpublished draft unless the draft exactly matches the published title, ADF body, parent, and owner; dispatch repeats that equivalence check immediately before mutation. Missing comparison fields are treated as divergent. The provider update then supplies only expectedVersion + 1, so Confluence's atomic version check prevents a superseded authorization from overwriting newer published content. The draft probes are defense in depth rather than an atomic guarantee: Confluence exposes no conditional update that prevents a draft created after the final probe from being merged or overwritten, and newly editable provider fields require explicit equivalence coverage, so callers that require draft-atomic publication must not use this action. Each published version persists the exact marker Control Center <authorized idempotencyKey> <payloadDigest>[ · <bounded versionMessage>] in its Confluence version message. The durable provider outcome separately records either the terminal provider-operation identity confluence-page:<pageId>:v<targetVersion> or, while an outcome is unknown, the reconciliation key cfpg:v1:<pageId>:<targetVersion>; neither is folded into the version marker. The normalized pluginConnectionId is an authenticated client-visible identifier used in typed HTTP route parameters and the browser's cross-tab synchronization storage key; it is not a credential or raw provider locator and must not cross an unauthenticated or public boundary. The verified Atlassian siteId, API credentials, and raw provider secrets remain server-private. None of those values are marker fields or canonical payload fields. A timeout, conflict, outage, or malformed post-write response becomes an unknown outcome, while a provider-declared invalid request is a confirmed rejection. Reconciliation reads the exact authorized version for that marker without replaying the mutation, so recovery can find it after arbitrarily many later edits. Because Confluence uses the same exact-version 404 for an absent version, a vanished page, and lost permission, and may omit version messages, those ambiguous observations remain pending instead of producing a false terminal failure. The retained marker keeps historical publication evidence attributable after later edits. Cancellation remains unsupported because the provider update is synchronous.

The canonical item page presents synchronized safe Markdown as an in-place visual editor for workspace owners. Saving always targets the exact normalized page and revision; Relay can draft against that same page before the owner confirms publication. Markdown task checkboxes on pages related directly to a release are counted in the release workset. A task-only update is enabled only when the normalized page explicitly proves that its Markdown can replace the provider ADF without losing structure; ordinary safe projections remain read-only because they deliberately omit destinations, media, raw HTML, and ADF round-trip metadata. Unchecked tasks, lazy page bodies, a truncated release graph, or an affected CodePipeline execution that is not waiting at an observed approval stage block a new Jira release-version publication. Every pipeline reached by a current pull-request delivered-by relationship is affected; each must expose a manual approval action or an approval-named stage and keep that stage running while the release is prepared.

While an enabled Confluence page is open and visible to a workspace owner, the browser performs one immediate connection-wide synchronization and repeats it every 15 seconds; saving or manually requesting a refresh can trigger an additional synchronization after current work settles. Same-origin browser tabs and mounted page controllers for the same connection share one foreground cadence. This foreground, owner-visible refresh is distinct from background scheduling: unbounded scheduled synchronization and webhook-driven synchronization remain deferred.

Confluence release templates are synchronized pages whose title contains the word template. Classification happens before the bounded 50-template hydration limit, so unrelated pages cannot hide a later template. The release agent loads only classified pages with exact readable content, places a copy in the release editor, and creates a separate Confluence page while the source remains unchanged. The durable canonical request is the governed-action envelope_json; its releasePublication structure persists the release ID, predecessor publication action, optional templateSourceEntityId, source-revision digest, and source-revision count. The publication idempotency digest binds workspace, release, provider and action kind, title, Markdown, parent, predecessor, source entity, Confluence page and expected version, source-revision digest, destination, and target entity. Provider credentials and private locators remain server-private and are never canonical payload fields.

Unbounded watcher/activity history, authoritative deletion evidence, background scheduled or webhook synchronization, and content search remain deferred to later Confluence milestones.

Clockify time-entry integration

makeClockifyReadPluginRuntime from @knpkv/control-center/server builds the production Clockify adapter around the shared Schema-validated ClockifyApiClient. The current descriptor negotiates entity.read, bounded sync.incremental snapshots on the time-entries stream, and governed action.propose, action.execute, and action.reconcile capabilities. Credentials remain in the externally supplied client layer.

The secret-free configuration names the root Clockify web URL, immutable workspace ID, comma-separated user IDs, page size, maximum pages, maximum concurrency, and per-request timeout. At most ten users are accepted, and user count multiplied by page size may not exceed 100 normalized entries in one aggregated provider page. Sync reads one page per configured user with bounded concurrency, stops at the configured provider-page limit, and deterministically splits normalized output so every emitted PluginSyncPageV1 remains within its 1 MiB UTF-8 envelope. A full final provider page uses a scope-bound bounded:<page>:<digest> checkpoint rather than claiming provider exhaustion.

Clockify's time-entry endpoint exposes offset pages but no stable snapshot cursor or window. Therefore resumable pages use an explicit restart:<digest> checkpoint: after an interrupted sync, the adapter restarts at provider page one and relies on stable event identities for idempotent replay instead of resuming at a mutable offset that could skip entries. Every checkpoint carries the SHA-256 digest of its workspace, ordered configured user set, and page bounds; changed sync scope and completed or bounded checkpoint replay also restart at page one.

Every provider response is decoded again at the adapter boundary before it becomes a normalized event. Time-entry facts preserve the configured workspace, provider user, project/task/tag IDs, billable and lock state, interval timestamps, provider duration, and explicit running/completed state. Provider interval timestamps supply source freshness; authentication, authorization, rate-limit, timeout, malformed-response, and outage failures remain in the closed plugin taxonomy.

Each governed Clockify proposal freezes a durable Schema.TaggedStruct payload. Both action variants bind the replay identity fields workspaceId, userId, entryId, and expectedRevision. correct-association additionally records desiredRevision, jiraIssueKey, originalDescription, correctedDescription, start, end, duration, projectId, taskId, tagIds, customFields, billable, and entryType; record-approval records decision and rationale.

correct-association replaces at most one supported leading Jira marker with the reviewed canonical [KEY] marker. It binds the exact normalized source revision and preservation fields, then sends Clockify a complete replacement containing the frozen start, end, project, task, tags, custom fields, billable state, supported entry type, and corrected description. Normal synchronization appends the successor entity and evidence revisions so relationship inference and rollups converge without rewriting history. Clockify exposes no conditional update or idempotency token for this operation, so dispatch performs a final reread, recognizes an already-visible desired state as a replay, and makes one initial update attempt. Only a confirmed rate-limit response with a retry instant no more than five seconds away permits one bounded second attempt; ambiguous responses become reconciliation-only work. Reconciliation rereads exact provider state and never replays the mutation; identity drift becomes a terminal failed reconciliation while unrelated malformed provider data remains a typed adapter failure.

record-approval is Control Center-owned. It records an approved or rejected decision in the durable governed-action ledger without calling a Clockify approval endpoint or changing the provider entry. Entity inspection accepts only the latest fully verified successful approval for the exact current Clockify source revision and displays the durable decision time; a later provider revision returns to pending while the historical action remains auditable. Post-dispatch cancellation is unsupported. The frozen 0.1.0 descriptor remains accepted as read-only, while the current 0.2.0 generation owns correction and approval.

Persistence boundary

The server entry owns one scoped libSQL client and an owner-only content-addressed object directory. The MVP schema is intentionally unstable: a fresh database is created from one checked-in schema snapshot, and an existing database must match it exactly. Schema changes are breaking and require recreating local development data. Versioned migrations start only after the persistence model is declared stable and a released database file must remain readable by a newer build.

Workspace-scoped repositories, optimistic revisions, and malformed-record quarantine keep durable state outside the browser. Large content bytes never live in normal SQL rows. Typed query plans live behind @knpkv/control-center-sql; raw SQL, query-builder types, filesystem handles, and resolved storage paths never cross the runtime service boundary. Local database and blob-root paths remain explicit, validated server configuration inputs.

The delivery graph is exposed to server workflows as one deep read/write module. Its atomic batches persist exact normalized entity revisions, explicit resolved or missing nodes, directional many-to-many relationships, and separately attributable evidence items and claims. Relationship and evidence revisions are append-only; confidence, provenance, lifecycle, release/environment scope, freshness, and retention remain domain data rather than UI inference. The SQL topology, digests, joins, and legacy pipeline-kind mapping stay private to the module.

A newly created configured data-root pathname is an atomic, relative symlink claim to a private sibling .control-center-incoming-* directory. The claim is deliberately retained: replacing it with a directory would reopen the no-clobber race that the claim closes. A move-preserving marker binds both the configured claim basename and the private target basename; startup validates that binding, ownership, and descriptor-pinned identity before using canonical operational paths internally. Existing real-directory data roots remain supported unchanged, except that .control-center-incoming-* is reserved for private publication targets and is rejected as a configured data-root basename.

Treat the configured symlink and its sibling target as one data-root unit for its whole lifecycle. Stop Control Center and every process that can write the data root before moving, copying, backing up, restoring, or deleting it. Use the offline backup and restore commands for portable backups; copying live SQLite files is not a safe backup procedure. While all writers remain stopped, operate on the containing parent tree rather than only the configured pathname; the relative claim remains valid after a parent-tree move. Do not dereference the symlink into a standalone copy or delete and recreate it while retaining its target. If the claim is lost and a marked sibling contains durable state, startup fails closed instead of silently creating a fresh database. Recovery is an explicit operator action: inspect the private sibling and verify the recovered unit before restarting. For a bound v2 marker, restore the configured pathname as a relative symlink to the marker's exact target basename. Marker-only siblings from an interrupted first publication carry no application state and do not block a fresh claim.

Version-one markers do not identify their configured claim. A direct real-directory v1 root can upgrade automatically, but no symlink-backed v1 root can: even a protocol-only target could be selected concurrently through another alias. For offline recovery, stop every writer, take and verify a backup, inspect the sibling target, remove the