Skip to content

TAN-840: reload operator-staged assertion keys with scoped hosted authority - #1935

Open
tacshade wants to merge 2 commits into
codex/tan-834-hosted-policyfrom
codex/tan-840-key-reload
Open

TAN-840: reload operator-staged assertion keys with scoped hosted authority#1935
tacshade wants to merge 2 commits into
codex/tan-834-hosted-policyfrom
codex/tan-840-key-reload

Conversation

@tacshade

@tacshade tacshade commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Hosted administrators cannot use the existing full-config reload because it requires deployment.admin. Add POST /admin/context-assertions/reload through the existing verified hosted.admin authority, current policy and protected host-effect audit. The request accepts no key material, path, token setting or provider configuration.

Load only the operator-configured metadata keyring; retain the existing issuer/audience/lifetime and durable replay store. Validate deployment scope, active validity and immutable key material; keep retirement/revocation monotonic and retain old key metadata. Record the candidate fingerprints in protected audit before publishing, then revalidate authority and compare the previous snapshot to avoid a concurrent overwrite. Invalid candidates and audit failures leave the previous verifier live. A successful response reports the published fingerprint.

Stacks on #1934. Current364d2092 passed focused authority/regression CI and Engine CI. Exact-source non-root engine integration at agents0cd167a passed overlap, retirement, malformed/wrong-scope retention, unauthorized reload, audit-anchor failure and replay across restart. Web5ee9c37 consumes that bundle and passed its real Linux installer and signer tests. Security Assurance passed every job, including Linux release composition and final engine-container composition.

This is part of TAN-840 signing lifecycle, not completion of the whole issue. Encrypted clean-host recovery, broader two-user privacy and product acceptance remain open. No automatic merge.

Signed-off-by: TacShade <198919272+tacshade@users.noreply.github.com>
@linear-code

linear-code Bot commented Sep 5, 2026

Copy link
Copy Markdown

TAN-840

Signed-off-by: TacShade <198919272+tacshade@users.noreply.github.com>
@tacshade
tacshade marked this pull request as ready for review September 5, 2026 23:10
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

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 Completed 2026-09-05T23:19:06.423575Z 364d209 Draft marked ready
ℹ️ 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 chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 364d209264

ℹ️ 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".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +276 to +277
for (kid, old) in before {
let new = after.get(&kid).ok_or("retain retired key metadata")?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject aliases of retired or revoked key material

When a staged candidate retains a retired or revoked entry but adds an active entry under a new kid with the same Ed25519 public key, this loop compares lifecycle state only at the original kid, so the transition is accepted. Assertions signed by the supposedly revoked private key can then use the new kid and authenticate again, defeating monotonic retirement and revocation; reject active aliases of previously non-active decoded public keys.

Useful? React with 👍 / 👎.

run: cargo test -p tandem-enterprise-contract hosted_policy --lib
- name: Validate scoped key lifecycle and administrative authority
run: |
cargo test -p tandem-server context_assertion_security --lib

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the required DCO sign-off

The reviewed commit message has no Signed-off-by trailer, so it violates the repository's mandatory DCO policy and will not satisfy contribution checks; add the sign-off to this commit's metadata before publishing it.

AGENTS.md reference: AGENTS.md:L38-L39

Useful? React with 👍 / 👎.

Self::ChannelConfigUpdate => "deployment.channels.manage",
Self::ChannelConfigDelete => "deployment.channels.manage",
Self::ChannelReload => "deployment.channels.reload",
Self::ContextAssertionReload => "hosted.admin",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor policy-projected hosted-admin grants

When the current hosted policy grants HostedAdmin through a member or organization-unit deployment_grant, the middleware projects that permission into strict_projection, but this host-action authorization checks only the assertion's raw capabilities for hosted.admin (or deployment.admin). A valid policy-granted hosted administrator therefore receives 403 unless the issuer redundantly embeds the capability; authorize this route against the projected AccessPermission::HostedAdmin authority as well.

Useful? React with 👍 / 👎.

grant
.revalidate(&state, &effect)
.map_err(super::host_authority::host_authorization_status)?;
*current = Some(next);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Revalidate candidate key validity immediately before publishing

When the candidate's sole active key expires while the protected audit append is awaiting ledger verification and durable I/O, the handler still publishes it because active validity was checked only before that await. This installs a keyring with no usable key and rejects all subsequent hosted assertions; rerun the time-sensitive active-key validation immediately before assigning the snapshot.

Useful? React with 👍 / 👎.

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