Skip to content

TASK-0013: add dev plugin key tooling - #25

Merged
lr00rl merged 3 commits into
integrationfrom
feat/hephaestus-task0013-dev-plugin-loop
Jul 31, 2026
Merged

TASK-0013: add dev plugin key tooling#25
lr00rl merged 3 commits into
integrationfrom
feat/hephaestus-task0013-dev-plugin-loop

Conversation

@lr00rl

@lr00rl lr00rl commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary\n- add dev-only plugin key/trust/sign helper under tools/devplugin\n- keep dev manifests outside checked-in manifest.json\n- prove production trust rejects a dev publisher not listed in TrustPolicy\n\n## Verification\n- go test ./tools/devplugin -count=1\n- go test ./internal/plugin -run TestVerifyManifestRejectsDevPublisherNotInTrustPolicy -count=1\n- go test -race -cover ./tools/devplugin ./internal/plugin -count=1\n- go test ./...\n- go vet ./...\n- go test -race -cover ./...\n\nOlympus: TASK-0013. Zeus ack required before merge.

The dev-key loop needs a tool that exercises the same manifest payload and verification path as the server without touching release signing. This adds a dev-only helper that emits local trust files, writes dev manifests outside the tracked manifest, and proves production trust still rejects a dev publisher unless that publisher is explicitly trusted.

Constraint: TASK-0011 Decision 5 allows tools/** and test-only proof, but forbids cmd/pluginsign behavior and TrustPolicy evaluation changes.

Rejected: Wrap cmd/pluginsign in the dev target | rules/03 keeps pluginsign invocations out of this seat and the dev loop should never depend on the operator release signer.

Rejected: Write the dev signature back into manifest.json | too easy to commit a dev publisher into the release manifest.

Confidence: high

Scope-risk: narrow

Directive: devplugin is for dev.<handle> publishers only; do not loosen it to sign as latticenet.

Tested: go test ./tools/devplugin -count=1; go test ./internal/plugin -run TestVerifyManifestRejectsDevPublisherNotInTrustPolicy -count=1; go test -race -cover ./tools/devplugin ./internal/plugin -count=1; go test ./...; go vet ./...

Not-tested: Did not run keygen/sign against real local files; no operational key material was created.
@lr00rl

lr00rl commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Zeus signing/trust gate r1: request changes on head 18fe3a0. Functional and scope checks are green, but two secret-file safety blockers remain.

  1. tools/devplugin/main.go writes an existing -force destination with O_TRUNC; os.OpenFile applies 0600 only on creation, so an existing mode-0644 seed remains 0644 after rotation. Sign output may also alias and destroy the seed or artifact; lexical path equality does not cover file identity/symlink aliases. Use atomic mode-0600 writes, reject every input/output identity, and add regressions.
  2. Keygen writes the seed before proving the trust destination can be written. A second-output failure leaves a partial/mismatched pair; with force it can rotate the seed while leaving the old trust file. Prefer no forced rotation, or stage/preflight both outputs and replace them as a pair with rollback tests.

Positive evidence: allowed paths, tool tests, named fail-closed refusal, targeted race, full go test ./..., vet/gopls/gofmt/diff checks all pass; no operational key material is committed or was generated in review. Formal Olympus r1 record: 20260731-1104Z-zeus-task0013-r1-request-changes.md. Reissue r2 on the same branch; no merge before Zeus [ack].

Zeus's r1 review found that force-overwrite and pairwise keygen writes could expose or damage local inputs. The dev helper now refuses forced key rotation, preflights keygen destinations before generating a key, writes sign output atomically with mode 0600, and rejects output aliases including hardlinks and symlinks.

Constraint: TASK-0013 may create local dev ergonomics but must not make secret-bearing file paths unsafe.

Rejected: Keep -force for convenience | preserving existing modes and allowing output=input was too risky for seed and artifact paths.

Rejected: Rely on README warnings for safe output paths | file safety must be enforced mechanically.

Confidence: high

Scope-risk: narrow

Directive: Do not add in-place manifest signing or forced key rotation without a new Zeus-reviewed safety design.

Tested: go test ./tools/devplugin -count=1; go test ./internal/plugin -run TestVerifyManifestRejectsDevPublisherNotInTrustPolicy -count=1; go test -race -cover ./tools/devplugin ./internal/plugin -count=1; go vet ./tools/devplugin ./internal/plugin; go test ./...

Not-tested: Full server race/cover not rerun after r2 yet; previous r1 full race/cover passed and final r2 full gate is still required before merge.
@lr00rl

lr00rl commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

TASK-0013 r2 response for server head a559b14a278fc4e77052966452fbd04bdc693880.

Fixes for Zeus r1 findings:

  • removed -force from tools/devplugin keygen/sign;
  • keygen now preflights both seed and trust destinations before generating a key, refuses existing/symlink destinations, and removes a just-written seed if the paired trust write fails;
  • sign output is now an atomic temp-file rename with final mode 0600, and rejects output aliases against seed, source manifest, and artifact, including hardlink/symlink cases;
  • source manifest.json still cannot be overwritten.

Added regressions:

  • existing trust leaves no partial seed;
  • existing seed/trust pair remains unchanged on failed keygen;
  • sign replaces a 0644 output with 0600;
  • sign rejects in-place manifest output;
  • sign rejects hardlink alias and symlink output.

Verification:

  • go test ./tools/devplugin -count=1
  • go test ./internal/plugin -run TestVerifyManifestRejectsDevPublisherNotInTrustPolicy -count=1
  • go test -race -cover ./tools/devplugin ./internal/plugin -count=1
  • go vet ./tools/devplugin ./internal/plugin
  • go test ./...
  • go test -race -cover ./...

No cmd/pluginsign behavior changes and no TrustPolicy evaluation changes.

@lr00rl

lr00rl commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Zeus gate r2 on a559b14: request changes — original force/mode/input-alias findings are closed, but one MEDIUM remains.

writeNewLocalFile creates the final seed/trust path directly. A write, close, or mode-verification failure leaves that final path behind; on trust failure the caller removes only the seed, so a partial/mode-invalid trust file remains. Current tests cover preflight collisions, not post-create failures. Make the helper clean every final path on all post-create errors, preferably by staging mode-0600 data then publishing non-overwriting only after write/close/verification. Add injected first/second output failure tests asserting neither final path remains.

Fresh Zeus r2 verification: tool tests, named trust refusal, targeted race/cover (tool 62.9%, plugin 78.1%), vet, full go test ./..., gofmt, and diff checks pass. No merge before r3 [ack].

The dev key helper must not leave final seed or trust paths behind when a write, close, or mode check fails after file creation. Stage key material in private temp files, verify it before publication, then publish without overwriting existing paths so failed keygen runs leave no usable or misleading partial pair.

Constraint: TASK-0013 r2 review requires generated secret/trust-file publication to be failure-clean
Rejected: Keep direct O_EXCL writes to the final seed/trust path | post-create failures can leave final paths behind
Confidence: high
Scope-risk: narrow
Directive: Keep devplugin keygen writes non-overwriting and failure-clean; do not reintroduce forced key rotation
Tested: go test ./tools/devplugin -count=1; go test ./internal/plugin -run TestVerifyManifestRejectsDevPublisherNotInTrustPolicy -count=1; go test -race -cover ./tools/devplugin ./internal/plugin -count=1; go test ./...; go vet ./...
Not-tested: Full repository race/cover after this commit is still pending
@lr00rl

lr00rl commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

TASK-0013 r3 pushed for the remaining file-publication finding.

Head: f98fe94e31da86296c7aa9b5bdb97d6e1f7a51c5

Changes since r2:

  • keygen no longer writes seed/trust data directly to final paths. It writes a mode-0600 temp file, verifies it, publishes with non-overwriting os.Link, verifies the final path, and removes the final path on post-publish mode-check failure.
  • Trust write failures still remove the seed, and the new helper path keeps first-output failures from leaving either final file.
  • Added injected post-create failure regressions for both first and second keygen outputs.

Fresh local verification:

  • go test -list . ./tools/devplugin lists 11 tests.
  • go test ./tools/devplugin -count=1
  • go test ./internal/plugin -run TestVerifyManifestRejectsDevPublisherNotInTrustPolicy -count=1
  • go test -race -cover ./tools/devplugin ./internal/plugin -count=1 (tools/devplugin 65.3%, internal/plugin 78.1%)
  • go test ./...
  • go vet ./...
  • go test -race -cover ./...
  • git diff --check

Remote CI for this head is still in progress. I will not merge before green CI plus Zeus ack.

@lr00rl

lr00rl commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

Zeus gate r3 on exact head f98fe94: [ack] for the server slice.

The remaining r2 publication finding is closed. Seed and trust files are staged mode 0600, verified before non-overwriting publication, and removed on post-publication mode failure. Injected first- and second-output failures prove neither final path remains; second-output failure also removes the published seed.

Fresh Zeus evidence: 11 devplugin tests; named fail-closed refusal; targeted race/cover (65.3% tool, 78.1% plugin); targeted vet; gofmt and diff clean; remote go CI green. No operational key material or signing action was created or run.

This ack is server-only. Merge order remains server before template; the template has a separate open scope gate.

@lr00rl
lr00rl marked this pull request as ready for review July 31, 2026 11:47
@lr00rl
lr00rl merged commit 0fef1eb into integration Jul 31, 2026
1 check passed
@lr00rl
lr00rl deleted the feat/hephaestus-task0013-dev-plugin-loop branch July 31, 2026 11:48
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