Skip to content

Scoped writer credential (EMR_WRITER_API_KEY) - #118

Merged
warheart1984-ctrl merged 1 commit into
mainfrom
feat/writer-credential
Oct 22, 2026
Merged

warheart1984-ctrl merged 1 commit into
mainfrom
feat/writer-credential

Conversation

@warheart1984-ctrl

Copy link
Copy Markdown
Owner

Follow-up to the recall credential (#101): a scoped credential for a second machine that should recall and write governed drafts without holding the ledger key (the full operator credential).

  • Scope: the seven read tools + emr_remember / emr_upsert, nothing else. emr_drift_check, the drift routes, the call log, the nx routes and every REST ledger route refuse it (401/403). MCP tools/list shows the nine; tools/call on anything else is AUTHORITY_DENIED / writer-credential-scope.
  • Headers: Authorization: Bearer or X-EMR-Writer-Key; not X-API-Key. The ledger key wins if both are presented and keeps working everywhere. The recall key stays read-only with a writer key configured.
  • Unchanged gates: writes still need JARVIS_MCP_WRITE_ENABLED=true, are drafts, and are refused without user_requested=true.
  • Startup: refuses a writer key shorter than 32 chars, equal to the ledger or recall key, or on a public deployment (where it is ignored).
  • stdio proxy: least privilege per tool (recall for reads, writer for the two writes, ledger only for the drift check).
  • Operator tooling: jarvisctl keys writer-key-init (key to secrets/writer.key mode 600 + one app.env line; never overwritten, never printed).
  • Docs: docs/writer_credential.md, cross-links, RFC appendix item 22.

What it does not do: it does not let the server tell machines apart (records still carry a client-chosen source_agent); that is RFC item 13, still unbuilt.

Tests: tests/test_writer_credential_boundary.py (22): every route in the isolation registry run with only the writer key; tool sets written out; strict mode; public deployment; startup checks; stdio. tests/test_deploy_keys.py (+3) for writer-key-init. Mutation-checked: 9 mutants on the credential (writer==operator, drift check in the set, recall accepted on writes, writer in X-API-Key, startup check off, full MCP surface, stdio prefers ledger, identity binding in strict mode, public deployment) and 4 on the CLI; each is caught (one survived at first, the strict-mode identity binding, and got its own test). Note: three mcp_server files use CRLF line endings; edits preserve them.

Not deployed. Deploying means recreating the app with the new image, and writer-key-init for the key.

🤖 Generated with Claude Code

…ber/emr_upsert drafts, nothing else

A second machine can write governed drafts without holding the ledger key. Same pattern as the recall credential, one step wider: credential_kind gains 'writer', MCP tools/list and tools/call are narrowed to WRITER_TOOLS, the two write tool routes accept the ledger or writer key (not recall), every other route refuses it, startup refuses a weak/duplicate/public writer key, the stdio proxy picks the narrowest key per tool, and 'jarvisctl keys writer-key-init' generates the key without printing it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-22T10:44:00.809856Z
We couldn’t complete this review. Comment @codex review to try again.
5adea0c PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@warheart1984-ctrl
warheart1984-ctrl merged commit 84c38d8 into main Oct 22, 2026
4 checks passed
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