Skip to content

Add scenario overlays#111

Merged
staverm merged 40 commits into
mainfrom
staverm/policy-pass
May 9, 2026
Merged

Add scenario overlays#111
staverm merged 40 commits into
mainfrom
staverm/policy-pass

Conversation

@staverm
Copy link
Copy Markdown
Member

@staverm staverm commented Apr 16, 2026

  • use and policies manifest syntax (gated on experimental_features: ["governance"])
    • use declares auxiliary components for governance purposes; they are resolved and validated but kept entirely out of the main scenario
    • policies declares an ordered list of policy capability refs in #use_name.export form
    • use components must be self-contained: no required root slots, no nested use or policies
    • Policy refs must resolve to an exported http provide with profile policy from the local use set
    • UI diagnostics
  • Governance artifact (linker)
    • The linker collects all policies-bearing components into scope builds, then assembles a synthetic governance scenario linking all referenced use components under a single governance root node
    • The governance artifact is linked as an ordinary component tree and threaded as a side-channel Governance value
    • Policy refs are mapped to synthetic exports on the governance root
  • Policy I/O models (policy/mod.rs)
    • PolicyInput (ScenarioScope) describes a governed subtree: components, internal bindings, imports, and exports, each tagged with an AttachmentId
    • PolicyOutput is a list of Interpositions - each declares an interposer component (program, config, slots, provides, resources) and a set of attachments mapping AttachmentIds to interposer slot/provide pairs
    • validate_policy_output checks capability type compatibility, required slots, and program validity before any graph rewriting
  • Policy pass (policy_pass.rs)
    • For each governed scope, builds a PolicyInput, invokes all declared policy exports, validates outputs, then rewrites the Scenario binding graph
    • Interposer components are inserted under the governed scope root
    • When multiple interposers attach to the same edge (across scopes or policies), they are chained in a deterministic order that semantically makes sense
    • GovernanceRuntime / GovernanceSession traits and CLI implementation
      • CliGovernanceRuntime::start builds a run plan from the governance scenario, launches policy processes via mixed_run, and proxies their exports as loopback HTTP endpoints; cleanup on all partial-failure paths
      • GovernanceSession::invoke_policy POSTs PolicyInput JSON to the export URL and deserializes PolicyOutput
      • Startup timeout surfaces policy process stderr on failure
    • Config interpolation through use entry configs (experimental)
      • ${config.x} references in use entry configs are composed against the scope root's config template at link time; unresolved refs (tracing to the scenario root) are collected and mirrored into the governance root's config schema so values flow to policy processes via the standard AMBER_CONFIG_* mechanism
      • $${config.x} preserves the reference symbolically, so policies can thread root config references into generated interposer config without materializing the value during governance execution (useful when interposers need secrets)
  • governance-redaction example: two A2A components governed by a Python policy that injects a redaction interposer. The policy receives a symbolic config reference for the redaction term and copies that symbolic ${config.secret} template into the generated interposer config, so the secret does not need to be materialized during governance execution.
  • Policy-generated interposers do not yet carry distinct synthetic provenance/identity. They currently reuse the root scenario manifest digest as their component digest and do not receive their own provenance/resolved_url entry.

edit: renamed governance to scenario overlays

@staverm staverm marked this pull request as ready for review April 23, 2026 10:59
@staverm staverm force-pushed the staverm/policy-pass branch from 6258c41 to ee23246 Compare April 28, 2026 09:25
@nhynes nhynes self-requested a review May 3, 2026 01:24
@nhynes
Copy link
Copy Markdown
Member

nhynes commented May 3, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: baae808e74

ℹ️ 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 thread compiler/src/linker/mod.rs Outdated
Comment on lines +1116 to +1118
ResolvedPolicyEndpoint::Provide { decl, .. }
if decl.kind == CapabilityKind::Http
&& decl.profile.as_deref() == Some("policy") => {}
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 policy exports that use non-HTTP endpoint protocols

This validation only checks capability kind/profile, so a policy export can pass linking even if its endpoint protocol is tcp. The CLI governance runtime then builds a tcp://... URL and calls reqwest::Client::post, which only supports HTTP(S), causing policy invocation to fail at compile time after an apparently valid policy ref. Please also validate the resolved endpoint protocol here (or otherwise enforce HTTP transport) so invalid policy manifests fail deterministically during linking.

Useful? React with 👍 / 👎.

Comment thread cli/src/governance_runtime.rs Outdated
Comment on lines +245 to +248
Ok(Err(err)) => {
return Err(GovernanceRuntimeError::message(format!(
"governance export proxy failed: {err}"
)));
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 Always stop the run before returning proxy-task errors

If proxy_task.await returns Ok(Err(_)) or a non-cancelled join error, this function returns immediately and skips mixed_run::stop_run, leaving governance processes/state behind. That creates leaked runtime state on proxy failures (e.g., repeated compiles can accumulate orphaned runs) instead of guaranteed cleanup. stop_run should run in all exit paths, even when reporting proxy errors.

Useful? React with 👍 / 👎.

@nhynes nhynes force-pushed the staverm/policy-pass branch from d2443d9 to da8cfcf Compare May 7, 2026 08:37
@nhynes nhynes force-pushed the staverm/policy-pass branch from da8cfcf to 05e1087 Compare May 7, 2026 09:05
Copy link
Copy Markdown
Member

@nhynes nhynes left a comment

Choose a reason for hiding this comment

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

LGTM. Please address the review comments from codex Also this is a great feature that is not just for governance. Could you do a rename pass to make it something more appropriately general of your choosing? Otherwise no other comments. Please merge when ready.

@nhynes
Copy link
Copy Markdown
Member

nhynes commented May 7, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: f7f9acd1ff

ℹ️ 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 thread compiler/src/overlay.rs
Comment on lines +294 to +301
let provide_decl = interposition
.interposer
.provides
.get(&attachment.interposer_provide)
.ok_or_else(|| ValidationError::UnknownInterposerProvide {
provide: attachment.interposer_provide.clone(),
})?;
if provide_decl.decl != *target_capability {
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 Validate attached interposer provide endpoints

When a policy attaches an interposer, this only checks that interposer_provide exists and has the right capability; it does not require the provide to name a valid program endpoint. For any HTTP/TCP target where the policy returns provides: { out: { kind: "http" } } or an endpoint name not present in the interposer program, the rewritten Scenario IR is accepted, but runtime planning later fails in resolve_provide_endpoint because every non-storage binding source provide must resolve to an endpoint. Please reject these policy outputs during policy validation so governance failures are attributed to the policy response instead of surfacing late during direct/compose/vm export generation.

Useful? React with 👍 / 👎.

@staverm staverm changed the title Add governance Add scenario overlays May 8, 2026
@staverm staverm merged commit 963efc5 into main May 9, 2026
39 of 40 checks passed
@staverm staverm deleted the staverm/policy-pass branch May 9, 2026 13:28
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.

2 participants