Skip to content

Vogt cutover 1.c: merge rust-core into main (VOGT_CORE_IMPL=python default) - #1208

Open
thedancingdeveloper wants to merge 908 commits into
mainfrom
rust-core
Open

thedancingdeveloper wants to merge 908 commits into
mainfrom
rust-core

Conversation

@thedancingdeveloper

@thedancingdeveloper thedancingdeveloper commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Cutover step 1.c (operator decision 2026-10-29): merge the Rust core line into main now that WI-2021 has landed. The swap stays behind VOGT_CORE_IMPL, default python (WI-2660), so this merge is not the cutover; step 1.d flips the default.

Behaviour changes on main even in python mode

  • vogt / vogt-mcp-remote are runtime symlinks in /opt/vogt/bin (first on PATH), chosen by VOGT_CORE_IMPL (default python). vogt-mcp stays the engine script.
  • New boot refusals (exit 78): unknown VOGT_CORE_IMPL, or missing/unwritable /opt/vogt/bin (affects read-only rootfs and non-image uids).
  • Engine image builds its own Python venv; no --build-arg CORE_IMAGE (WI-1078); ~122 MB larger.
  • Migration observed/0007_coverage_index (adds idx_sweeps_finished) applies in python mode. Rollback to an older image needs DROP INDEX idx_sweeps_finished; DELETE FROM migrations WHERE id='0007_coverage_index' on observed.sqlite3.
  • instance.clone has no REST route (POST /api/instance/clone removed); registry/describe shows null http_method/http_path for local-only ops.
  • CLI flags taking a nested model (e.g. watch.create --trigger) take one JSON object.
  • Engine (both modes): idle sessions past the retain window are hidden even while alive (WI-2689).
  • CI/release tooling: version check, config-doc generation and e2e fixture reset run through vogt-core (WI-1079).

Merge method

Squash (the branch has 814 commits incl. hand-resolved merges; rebase would replay them). Before merging: git tag archive/rust-core-1c <head> && git push origin archive/rust-core-1c. After: git diff --exit-code <head> origin/main must be empty.

🤖 Generated with Claude Code

sprooty and others added 30 commits October 18, 2026 11:49
…orts (WI-1076)

Both jobs share the runner's Docker daemon. The compose job's smoke held
127.0.0.1:18080, so the live job's bring-up failed with 'port is already
allocated' and the compose job failed the same way. Each job now names its
own Compose project and host ports. The smoke takes VOGT_PORT and
ENGINE_PORT from the caller, defaulting to its old values.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…WI-1076)

Operator decision, 2026-10-17. The live suite fails 89 of 184 specs on the
Rust core (run 39024313197), and main's Python core fails the same specs.
The required job now runs the three gating specs (login errors, stale demo
provenance, terminal replay budget) fatally. The rest of the live suite runs
after it, advisory, and is tracked as a follow-up.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
Fixed ports still clashed: the compose smoke failed with 'Bind for
127.0.0.1:18080 failed: port is already allocated' on a runner whose
daemon is shared, after the move off that port by the live job. Each step
now takes free host ports at run time, and the smoke does the same unless
the caller sets them.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
assistant.rs's real-core test lives inside the crate and only checks the
canned reply. This runs a turn through /api/assistant/message with a stub
model: the model asks for vogt_status, and the tool result it gets back
must be the Rust core's own status. The break-glass token carries the
assistant capability and lends the stack secret to the core.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…(WI-1076)

The 'core alone' CI job deletes engine/, web/ and mobile/ and runs all of
pytest. The Rust dump cannot run without engine/, so it skips there, the
same way it skips without cargo.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
Python's grant view reads the clock once per row, so an empty list reads
nothing. The Rust list read it once up front, which advanced a shared step
clock by one tick and shifted every later timestamp in an MCP session.
Found by the MCP parity run (WI-1764).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…golden (WI-1764)

The MCP runner never started the stand-in engine and kept no seen answers,
so the grant_decide and grant_revoke steps could not resolve their grant id.
It now runs engine steps against the stand-in, restarting the server when the
engine flag changes, and reads {seen:...} references as the CLI run does.

The MCP golden is re-recorded from Python. Rust and Python agree over MCP,
including the audit payload_digest. The CI parity sequence now records and
checks the MCP transport too, so this comparison runs on every push.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
check-route-map.mjs now also asserts that every write vogtApi.ts exports
collects a reason, and that every engine path the bundle names is served
by engine/server/src/app.rs and listed in docs/ENGINE.md. It strips
comments the way tests/test_pwa.py does, so a commented-out route no
longer counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
scripts/check.sh's web half and the CI engine job now run
web/scripts/check-route-map.mjs, so the ported check gates the tree once
tests/test_pwa.py is gone. A PR that only changes the registry golden now
also triggers the engine job.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…1077)

playwright.config.ts registers a live-phone project (iPhone 13) next to
live, selected explicitly, so the phone-size live run is reproducible.
docs/parity/live-playwright-rust-vs-python.md records the desktop and
phone live runs on both cores: no test fails on Rust only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
… store (WI-1053)

The Python core writes a declared store (tests/parity/make_python_auth_db.py):
an issued API token and a password login. The Rust core opens a copy and must
authenticate the token with its actor and scopes, sign the user in with the
Python scrypt hash, and refuse wrong secrets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…uoting (WI-1079)

scripts/fake-agent now execs `vogt-core fake-agent` ($VOGT_CORE_BIN, PATH,
then the checkout's cargo build) and no longer falls back to
fake_agent_core.py. The e2e engine image stops copying the Python core.

Running the contract and engine integration suites through the Rust port
showed the steer echo used Rust Debug quoting ("go") where Python printed
repr ('go'); a py_repr helper restores the Python form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
… present (WI-1079)

The core-alone CI job deletes engine/, so scripts/fake-agent has no binary
to exec there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
….py (WI-1744) [WIP, gates pending]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…result_large_err) (WI-1744)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…d fixtures to vogt-core (WI-1765)

Peak is the largest turn, compaction marker wherever it sits, output counted
once per turn across blocks, and the five shared economics fixtures asserted
with the Python meter's numbers. Disposition doc marks the file ported.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…e port (WI-1080)

Signed-off-by: sprooty <sprooty@sprooty.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…thon floor (WI-1080)

Measured 80.22% lines at rust-core a5ac4cb.

Signed-off-by: sprooty <sprooty@sprooty.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-1745)

Port the test_forge_publish.py gate cases into forge_ops_test.rs: an empty
repository, a detached HEAD, the branch and revision read, a dirty tree
named by path, and the no-credential refusal before anything is created.
The already-linked refusal now also asserts the forge link pointer.

The disposition row stays unported for the work.create write-through
(WI-1068) and the git argv no-force spy (WI-1072).

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
Port two test_forge_import.py cases into forge_ops_test.rs: the display-name
override names the project and derives its slug, and an imported project
(linked on import) takes a forge.writeback policy.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…1745)

Port the test_forgejo.py backlog, watermark and closure cases into
forge_ops_test.rs, driven through sweep against a Forgejo host configured
under forge_token_files with a stand-in transport:

- issues and pull requests reach the ranked backlog, and the sweep only reads
- the second sweep asks for what moved since the first watermark
- an issue closed upstream leaves the backlog, and its subject's latest
  observation is closed under the provider's own key scheme

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…s (WI-1745)

Port the forge-module cases of test_forge_module.py into a sibling
forge_module_test.rs, on the Forgejo stand-in for the provider-neutral
service logic and a GitHub stand-in for the drift cases that read gh:
subject keys and the posture facts. Covers read-only onboarding and its
audit row, the closed-history filters, brief and backlog agreement, the
default none policy and its ledger, drift in both directions, the adopted
link and reopen rules, the automation gap and the demo.

The upstream consequence of a write-back (posting the comment, closing the
linked issue) is not wired in the core yet; those two cases are recorded
as unported in the disposition row rather than faked.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…745)

Port the cases of test_upstream_truth.py that need no write-through into
upstream_truth_test.rs: a vogt-only change on an adopted item sends nothing,
the unlinked refusal and the local-only paths, projectless items, each
upstream issue counted once in the backlog and board, the relation refusal,
forge.link's no-repo-URL refusal and its audit row, and the policy-none
create refusal with every gate named.

The disposition row records what the core does not do yet: create, comment,
close and label write-through; board visibility of upstream-only issues and
cursor paging; and title, body and label-removal refusals on an adopted item,
which the core accepts locally.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
test_public_delivery.py reads the deploy files and the Dockerfiles as text,
and two cases run docker compose config. None calls the core, so the row
names the reason it is retired rather than a port.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…(WI-1745)

Address the three review blockers on WI-1745:

- Board: the board lists declared rows only, and the cursor is not honoured
  on page two. Pinned by two ignored tests.
- Parity: title and body edits and label removal on an adopted item are
  accepted locally, where Python refuses them as upstream truth. Pinned by
  two ignored tests.
- Comment and close write-through: the disposition row now says no work item
  is filed, rather than naming WI-1068, which covers only the work.create
  write-through.

The four ignored tests fail as expected. Work items for the gaps are not
filed yet: work_create is refused by the vogt project's write-back policy.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
… (WI-1745)

File WI-1778 (board), WI-1779 (upstream-truth edits) and WI-1780 (comment and
close write-through) local-only, as the operator chose, because the vogt
write-back policy is none. The ignored regression tests and the disposition
rows now cite these refs.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
…h gap at WI-1780 (WI-1745)

Signed-off-by: sprooty <sprooty@sprooty.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
project.import through a recording cloner and clone_repository against a
real local git. The subprocess spies have no seam in run_git and stay
unported. Unported WI-1745 rows now say "Deferred to WI-n", as rust-core's
disposition test requires.

Signed-off-by: sprooty <sprooty@sprooty.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…747)

The two audit-row claims in test_front_door.py were checked against the
engine's stand-in core. They now boot the real vogt-core binary, write
through the engine's door, and read the audit table back with
`vogt-core audit list`. The other front-door tests keep the stand-in.

http-test-map.md: both rows move from partial to covered.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Signed-off-by: sprooty <sprooty@sprooty.com>
thedancingdeveloper and others added 30 commits November 4, 2026 19:31
…it ignore (#1297)

Graft-Changeset: c5da4b2944b55b5547c71b2edda5ae644f8f44cb63c2823b43f863ecb86cd1858
Graft-Session: ses_01M6HTGFFZMGE99F6QNKWRRXHS
Graft-Work-Item: WI-3162
Graft-Batch: 72
…ap tests (#1297)

A session recovered after a restart kept its account slot if it was stopped
or removed without being woken. remove() and stop() now drop the lease, and
AccountPool::restore returns the lease itself so a restored slot cannot be
held without something to release it. Tests cover wake, failed start,
restart+remove, restart+stop and a live stop by registry and endpoint.

Graft-Changeset: ccaf1c6ad88fe1f4908aec8851ba694a43339c7778fa79a6b0d2f90c486afdb8a
Graft-Session: ses_01M6HTG7X7J8MEF1JBC9MMAKEK
Graft-Work-Item: WI-3159
Graft-Batch: 72
…WI-3132)

Graft-Changeset: cd376e19c052118bc98e233fd6f0f471f0022346b4f97e3c02a01e345f5aca70d
Graft-Session: ses_01M6J5Z9S3FCN62MQDJH5SHHE0
Graft-Work-Item: WI-3132
Graft-Batch: 72
… last_reply and digest (WI-3133)

session.wait_any: timeout_s defaults to 300; an oversight caller's value is
raised to 60 so a short wait cannot become a poll loop; the answer carries the
changed session's digest. session.last_reply and session.digest take 'since'
and return {unchanged: true, cursor} when the body is unchanged.

Parity goldens (registry, mcp-tools, openapi, validator corpus) are updated by
hand to the Rust schemas; Python must mirror before test_rust_schemas passes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Graft-Changeset: c3623d75a752b04d6c5bee65c5b65a23180007e529d5edff4ef37b2404d4ba7e1
Graft-Session: ses_01M6J5ZD8Q0YDC6FYGESKXSR8Q
Graft-Work-Item: WI-3133
Graft-Batch: 72
… compactions (WI-2832, WI-2043)

Graft-Changeset: ca19ba582a8df739218c5725eed649b6d009a2a8fb4bd284f991951e89d80b77f
Graft-Session: ses_01M6J71AZ1AZNKXD5Q3886AH09
Graft-Work-Item: WI-2832
Graft-Batch: 72
…the worker set, full only when asked (WI-2833)

Graft-Changeset: c7bdbf83e9d6346e9899695d19ffdc714bd361062d0b35ddb99c107f5c52c43be
Graft-Session: ses_01M6J71EM2V5PC9EJKEVDKPN37
Graft-Work-Item: WI-2833
Graft-Batch: 72
…Codex auto-compact limit (WI-1575)

Graft-Changeset: c4f52c8b14b0f5665a9eba8b2723f39a50fc53e2b0f0f8c84f5d31661bae83b66
Graft-Session: ses_01M6J7NKK9PS7BC0NAPSQKA67Y
Graft-Work-Item: WI-1575
Graft-Batch: 72
…_by/since (WI-1525)

Graft-Changeset: c77c76ec4904bc75dc07da892a0ed7fdf9eee4bf9a5a803db341444f7e157e90b
Graft-Session: ses_01M6J71JD4CNXGQZ1F0J22HR2J
Graft-Work-Item: WI-1525
Graft-Batch: 72
…ad of hibernating; default 200k context budget (WI-1522)

Graft-Changeset: c0ec0e1da835748a6625df72faa91d5d11cd6621530a9e8c6444a8e7eda60a53c
Graft-Session: ses_01M6J963WGM45K9XVJNMNK5PY2
Graft-Work-Item: WI-1522
Graft-Batch: 72
…test the real entrypoint (#1297)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Graft-Changeset: ce6d4b2a7f7066aa9f7a35d7894a5e7386ab6ea12c10d9d7cff175e9c6fdf181d
Graft-Session: ses_01M6HTFK3M9D1RWMEJZYVD5HBF
Graft-Work-Item: WI-3163
Graft-Batch: 72
PodConfig now reads ENGINE_POD_* (VOGT_ENGINE_POD_* accepted as an alias):
namespace, image, engine endpoint, service account, image-pull secret,
priority class, cache objects, resources. Plain-http endpoint only with
ENGINE_POD_ALLOW_INSECURE_ENDPOINT=true; https stays required by default.
Empty cache names leave the cache out of the pod. Adds a built-in "Pod"
template (backend=pod) and deploy/smoke/{engine,smoke}.env for smoke-pod.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Graft-Changeset: c5a5b9435b1c0fe9dc94d49256755db51edc0bf04b9a0488dc57f201361a33f8c
Graft-Session: ses_01M6HTFK3M9D1RWMEJZYVD5HBF
Graft-Work-Item: WI-3163
Graft-Batch: 72
…h backoff (WI-3163)

kube-router admits a new pod's IP into the engine allow-set 1-3 s after start;
until then the engine refuses the connection. Retry refused/timeout/5xx with
250 ms doubling backoff (2 s cap, 15 s total); 4xx is final. Applies to the
entrypoint bootstrap curl and the agent websocket connect. The entrypoint error
now names the curl exit code and time waited.

Graft-Changeset: cea41c971654bb84f76ebed9cb20e94a45704c99f2f9e9655c8da24c63b14ab6e
Graft-Session: ses_01M6J5J83ZJ2Z4MPN8DXDF8503
Graft-Work-Item: WI-3163
Graft-Batch: 72
…e (WI-3163)

A pod that died after bootstrap left no usable cause. Print a step marker to
stderr before each phase and include graft's own error, the repo, line and
GRAFT_ENDPOINT in the clone failure.

Graft-Changeset: c501ebbdeea7d59504785466779a4ef1dd4271d47dae61136933f59cb69b56cf6
Graft-Session: ses_01M6J5J83ZJ2Z4MPN8DXDF8503
Graft-Work-Item: WI-3163
Graft-Batch: 72
…to session pods (WI-3163)

The pod had no graft endpoint, so g clone failed. ENGINE_POD_GRAFT_ENDPOINT is
engine config, sent in the bootstrap env with GRAFT_LINE; ENGINE_POD_GRAFT_TOKEN_FILE
names a mounted secret the engine reads at bootstrap and returns as graft_token,
which the entrypoint writes to a 0600 file and clones with. Smoke config points
at the in-cluster graft-dev Service. Engine-side minting of a per-session
scoped token is follow-up.

Graft-Changeset: cd7053dd604e05c26f11e7bf086fbe2f545d34909811ea9b008332d028ceff8f8
Graft-Session: ses_01M6J5J83ZJ2Z4MPN8DXDF8503
Graft-Work-Item: WI-3163
Graft-Batch: 72
…and stream end (WI-3163)

The agent logged nothing after the entrypoint handoff (default filter was
error-only), so a missing attach could not be told from a missing connect.
Default to info on stderr and log each stage.

Graft-Changeset: ce3d5c42737f3b59bc1842407ad0e5e62c9ede11f18de799dcb887ecbc3fc35fe
Graft-Session: ses_01M6J5J83ZJ2Z4MPN8DXDF8503
Graft-Work-Item: WI-3163
Graft-Batch: 72
Graft-Changeset: c942437829dad6914830241712c1ce2c0059d0cfba65f1a1c4441235e58f4c14c
Graft-Session: ses_01M6JB77H29Y09SSEQR4K7RXN8
Graft-Work-Item: WI-3163
Graft-Batch: 72
…ut and resize (WI-3163)

Graft-Changeset: cc7dbbfc3c656d592e80ed7032bc221db927118dac61ae5302777629582d33a3d
Graft-Session: ses_01M6JB77H29Y09SSEQR4K7RXN8
Graft-Work-Item: WI-3163
Graft-Batch: 72
…plays output; log pod start (WI-3163)

Graft-Changeset: c5fec2957e59f2266edc5ef942a292c61ecc6d0717f8429a1ce46c6ea100e109e
Graft-Session: ses_01M6JB77H29Y09SSEQR4K7RXN8
Graft-Work-Item: WI-3163
Graft-Batch: 72
…od template

Graft-Changeset: ca98b7c679df11af602c2f1e69ded49396382a9f8e092061d7cc420b476e38771
Graft-Session: ses_01M6JJ07C4MKX00ZVMYEJFKCQC
Graft-Work-Item: WI-3163
Graft-Batch: 72
…ts by offset (WI-3160, #1297)

Files and directories are created 0600/0700 with O_NOFOLLOW instead of chmodded after.
Transcripts are append-only deltas at an expected offset: the engine appends only at its
length, accepts an identical duplicate, and answers 409 with the offset to resync from;
the agent sends bounded deltas and follows the resync. Credentials stay whole-file newer-only.

Graft-Changeset: cef760e3b24b2ecaf1073a19269e77176fd024a5a481dd36dbc35189f97b0e014
Graft-Session: ses_01M6HTG17DCTZ8453HJKSJ85ER
Graft-Work-Item: WI-3160
Graft-Batch: 72
…D: pod smoke pending)

The engine answers a refused hole with Resync{offset}; the agent resends from
there if it still holds the bytes, else sends Gap{offset,lost} and the engine
records '[N bytes lost]' and continues. Tested with the in-test fake agent.

Graft-Changeset: c01cffa2e703cb4fd1578c44e835df03d904e3edd0b7be2f37e4c22521d5721f5
Graft-Session: ses_01M6HTG7X7J8MEF1JBC9MMAKEK
Graft-Work-Item: WI-3159
Graft-Batch: 72
…start (WI-3158, WI-3205)

Graft-Changeset: c310cc9b9968c9fde029d148a0e8d376b4c67e49cbd799179aea23fba280e41a3
Graft-Session: ses_01M6HT5TCKMS31M945SD6ZRHHJ
Graft-Work-Item: WI-3158
Graft-Batch: 72
…start (WI-3158, WI-3205)

Graft-Changeset: ca28c0e3d6a8cae5528b1cc563c845634a74f5a233d3fa3bd9a494e4d665dc82b
Graft-Session: ses_01M6HT5TCKMS31M945SD6ZRHHJ
Graft-Work-Item: WI-3158
Graft-Batch: 72
…last, carries permission mode/autopilot/budget; drop lib.rs.orig (WI-3132)

Graft-Changeset: c22c28d853a4ab4e6914372e66219ddd779e7fb186e202cd28ea440d022a3e059
Graft-Session: ses_01M6JQZ6YGBWK4Y4H10AMHGY34
Graft-Work-Item: WI-3132
Graft-Batch: 72
…ion; deny: dated advisory ignores (WI-3229)

Graft-Changeset: c126441975ebb910e24c77ec9c2ee46076f690cd0f2c2c1e15b68b480f44fed00
Graft-Session: ses_01M6JQSZCPB2KNCV6T8WRQ9Z7S
Graft-Work-Item: WI-3229
Graft-Batch: 72
…ery bundle refusal; private temp configs, persisted config version, bundle rate limit and body bound (WI-3160)

Graft-Changeset: cf38ff6685157cbd3a840ef76f4eb8a449074e2e4695058d5871d11f385a92280
Graft-Session: ses_01M6JQZ1DBR387R2ZRZY989MY3
Graft-Work-Item: WI-3160
Graft-Batch: 72
…env (WI-3231)

The single-use bootstrap credential is no longer a pod-spec env value. The
engine creates the pod, then a per-session Secret owned by it (ownerReference,
so it is collected with the pod), mounted read-only at /run/vogt-bootstrap with
mode 0400. The entrypoint reads it from VOGT_BOOTSTRAP_TOKEN_FILE. If the Secret
cannot be created the pod is deleted. Requires create/delete on secrets in the
sessions namespace for the engine Role (ops/k8s).

fix(engine): unique bootstrap Secret name per pod so the engine never deletes Secrets (WI-3231)

The Secret name carries a random part, fresh for every pod, so a stale Secret
of the same session can never collide. The stale-replace path is gone; the
engine Role needs only secrets: [create]. A failed Secret create still deletes
the pod (and only the pod).

Graft-Changeset: c63df259d5ed0dda2951c945fc24c2c6c28df5228fc6d39d2b1fef73c686be4db
Graft-Session: ses_01M6JTMVZNVT03VWXXY6WK8FDK
Graft-Work-Item: WI-3231
Graft-Batch: 73
…markers, guard write_private (WI-3232)

test(engine): route credential claims through a testable broker method, clippy fixes (WI-3232)

Graft-Changeset: c9ef9188938e60d4df14ccc1d8d6d5ab059e475cfa7cfbb00e2bc73f9891e5ef6
Graft-Session: ses_01M6JW0GMC2F1N5F01005AVWDS
Graft-Work-Item: WI-3232
Graft-Batch: 73
Graft-Changeset: c5e2cf4b531963244d84ee0c5a5b184af93d2757c17c4c4bf99ecb5ae8c87e582
Graft-Session: ses_01M6JYES5H2S50HVD2HD8G7B4C
Graft-Work-Item: WI-3233
Graft-Batch: 74
…hdraw unused bootstrap token, document write-limit reset, keep rotation claim on unknown start outcome (WI-3234)

Graft-Changeset: cea92f1a3cf9f8e73b9f7242acfd64e7daf39fbbf4486c71d3b88fd3167af78e1
Graft-Session: ses_01M6JZATPQBKPF806RQGKHZAK4
Graft-Work-Item: WI-3234
Graft-Batch: 74

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant