Implement pilot allowlist on the upload-claim issuer - #109
Merged
Merged
Conversation
…urce
- New trace_upload_claim_allowlist module: hash_invite_code helper
(sha256:hex(sha256("invite:" + code))), AllowlistSourceSpec parser
(file:<path> works, near:<account>:<view> reserved-but-rejected),
AllowlistFile/Snapshot/Entry schema with version pinning and strict
canonical-lowercase hash validation, AllowlistSource trait,
FileAllowlistSource with cached + refresh-interval reload + cache-on-
transient-error semantics, DenialCounter sliding-window helper.
Eight unit tests cover hashing, source parsing, schema rejection,
dedupe, refresh-cache, fallback-to-cached on delete/corrupt,
first-load failure path, and denial-counter window eviction.
- WorkloadClaims gains invite_code: Option<String> (Slice 2 reads it).
- UploadClaimClaims gains policy_label: Option<String> with
skip_serializing_if so existing clients see no JWT-shape change.
- IssuerError gains the four PilotAllowlist* refusal vocabulary
variants (NotMatched 403, InviteCodeMissing 400, Stale 503,
Malformed 503). Marked allow(dead_code) until Slice 2 invokes them.
No behavior change for existing deployments: every new field is
Option<None> on the issuance path; allow-lists are off-by-default.
…ion tests - TraceUploadClaimIssuerConfig gains allowlist_source / refresh_interval / max_stale / admin_bind; from_env reads four new env vars (off by default). - build_state warms the FileAllowlistSource eagerly so a missing or malformed file fails startup, refuses Near sources with the reserved- but-not-implemented error label, and enforces a loopback guard on admin_bind (override via TRACE_COMMONS_ISSUER_ADMIN_BIND_ALLOW_PUBLIC=1). - TraceUploadClaimIssuerState carries the optional source + max-stale duration + DenialCounter; pub(crate) accessors live on the state for Slice 3's admin module to consume. - New enforce_pilot_allowlist helper runs before any other issuance validation: missing invite_code → 400, malformed source → 503, stale snapshot → 503, subject_hash not in snapshot → 403 + denial-counter increment. All four refusals log hash-only warnings with the matching error_class label. Successful match returns the snapshot's policy_label, which the minted UploadClaimClaims now carries. - Five integration tests via the existing post_claim harness: admit-and- embed-policy_label, refuse-unlisted, refuse-missing-invite, off-by- default-back-compat, stale-snapshot-refusal. Existing tests untouched. Behavior for deployments that don't set TRACE_COMMONS_ALLOWLIST_SOURCE is byte-identical to pre-slice main.
- New trace_upload_claim_issuer_admin module: AdminState + admin_router() exposing GET /v1/admin/allowlist-status. Returns configured / source_label / policy_label / entries (count) / snapshot_age_seconds / denials_last_hour / max_stale_seconds / stale. Identity-revealing fields (subject_hash, tenant_id, note_label, raw invite codes) never appear. Four unit tests with a static fixture source confirm both shape and absence-of-identity-fields. - serve_trace_upload_claim_issuer now builds state once and spawns both axum::serve futures (public + optional admin) under one shared shutdown signal. The public router is rebuilt via a state-taking helper so the admin bind sees the same Arc<State> (same denial counter, same allowlist source). The pre-refactor serve_router_with_graceful_shutdown helper stays for the existing graceful-shutdown test. - TraceUploadClaimIssuerState gains build_admin_state() so the admin module never reaches into private fields. - trace-commons-upload-claim-issuer binary gains --hash-invite-code <CODE>: prints sha256:<...> via the same hash_invite_code helper the issuance handler uses. Single source of truth between the operator's allowlist file and the runtime check. - docs/operator/pilot-allowlist.md: full operator runbook — what-the-gate-does, how-to-provision-an-invite-code (incl. a /dev/urandom one-liner), the JSON schema with field semantics, required + optional env vars, reading /v1/admin/allowlist-status, denial-smoke procedure, mid-pilot adds, rollback, signer-side coordination notes, and known limitations. - docs/operator/README.md: cross-link row. - README.md: "Contributor gate" row in the pilot-status table. - Slice 2's dead_code allows on IssuerError::pilot_allowlist_* are now actually-used and removed. All four CI-style gates green locally: cargo check default, cargo check --features near-ai-scorer, cargo test, no clippy warnings. Behavior for deployments that don't set TRACE_COMMONS_ALLOWLIST_SOURCE remains byte-identical to pre-slice main.
This was referenced May 18, 2026
Merged
zmanian
added a commit
to nearai/ironclaw
that referenced
this pull request
May 19, 2026
Companion to TraceCommons/trace-commons#109 — the trace-commons server-side invite-code allowlist landed there with refusal labels PilotAllowlist* (NotMatched 403, InviteCodeMissing 400, Stale 503, Malformed 503). This commit teaches the Ironclaw trace client three things: 1. Carry the invite code through the standing policy. - StandingTraceContributionPolicy gains upload_token_invite_code: Option<String>, serde-default + skip-if- none so existing policy files keep parsing byte-identical. - TraceUploadClaimIssuerRequest body gains an optional invite_code field (forward-compat for a future server slice that may read it from the body in addition to the workload-JWT claim). - trace_upload_claim_cache_key keys on the invite code so a mid- pilot rotation forces a fresh claim mint. 2. Surface the typed allowlist refusal labels. fetch_trace_upload_claim_from_issuer now parses {"error": "<Label>"} bodies on non-success status and maps each PilotAllowlist* label to a user-actionable diagnostic. 3. CLI flag + status surface. ironclaw traces opt-in --upload-token-invite-code <CODE> (off by default). ironclaw traces status and queue-status report "pilot invite code: configured / not configured" — never echo the raw code. After the trace-client extraction (5e568fc + 23104c9), the trace contribution code lives in crates/ironclaw_reborn_traces. The invite- code wiring lands on the extracted paths. Seven new unit tests, all green: - standing_policy_serde_back_compat_when_invite_code_missing - standing_policy_serde_round_trips_invite_code_when_set - standing_policy_serde_omits_invite_code_when_none - cache_key_distinguishes_different_invite_codes - parse_trace_upload_claim_error_label_handles_known_shapes - opt_in_invite_code_flag_parses_through_cli - opt_in_invite_code_defaults_to_none_when_absent
zmanian
added a commit
to nearai/ironclaw
that referenced
this pull request
May 20, 2026
Companion to TraceCommons/trace-commons#109 — the trace-commons server-side invite-code allowlist landed there with refusal labels PilotAllowlist* (NotMatched 403, InviteCodeMissing 400, Stale 503, Malformed 503). This commit teaches the Ironclaw trace client three things: 1. Carry the invite code through the standing policy. - StandingTraceContributionPolicy gains upload_token_invite_code: Option<String>, serde-default + skip-if- none so existing policy files keep parsing byte-identical. - TraceUploadClaimIssuerRequest body gains an optional invite_code field (forward-compat for a future server slice that may read it from the body in addition to the workload-JWT claim). - trace_upload_claim_cache_key keys on the invite code so a mid- pilot rotation forces a fresh claim mint. 2. Surface the typed allowlist refusal labels. fetch_trace_upload_claim_from_issuer now parses {"error": "<Label>"} bodies on non-success status and maps each PilotAllowlist* label to a user-actionable diagnostic. 3. CLI flag + status surface. ironclaw traces opt-in --upload-token-invite-code <CODE> (off by default). ironclaw traces status and queue-status report "pilot invite code: configured / not configured" — never echo the raw code. After the trace-client extraction (5e568fc + 23104c9), the trace contribution code lives in crates/ironclaw_reborn_traces. The invite- code wiring lands on the extracted paths. Seven new unit tests, all green: - standing_policy_serde_back_compat_when_invite_code_missing - standing_policy_serde_round_trips_invite_code_when_set - standing_policy_serde_omits_invite_code_when_none - cache_key_distinguishes_different_invite_codes - parse_trace_upload_claim_error_label_handles_known_shapes - opt_in_invite_code_flag_parses_through_cli - opt_in_invite_code_defaults_to_none_when_absent
zmanian
added a commit
to nearai/ironclaw
that referenced
this pull request
May 22, 2026
Companion to TraceCommons/trace-commons#109 — the trace-commons server-side invite-code allowlist landed there with refusal labels PilotAllowlist* (NotMatched 403, InviteCodeMissing 400, Stale 503, Malformed 503). This commit teaches the Ironclaw trace client three things: 1. Carry the invite code through the standing policy. - StandingTraceContributionPolicy gains upload_token_invite_code: Option<String>, serde-default + skip-if- none so existing policy files keep parsing byte-identical. - TraceUploadClaimIssuerRequest body gains an optional invite_code field (forward-compat for a future server slice that may read it from the body in addition to the workload-JWT claim). - trace_upload_claim_cache_key keys on the invite code so a mid- pilot rotation forces a fresh claim mint. 2. Surface the typed allowlist refusal labels. fetch_trace_upload_claim_from_issuer now parses {"error": "<Label>"} bodies on non-success status and maps each PilotAllowlist* label to a user-actionable diagnostic. 3. CLI flag + status surface. ironclaw traces opt-in --upload-token-invite-code <CODE> (off by default). ironclaw traces status and queue-status report "pilot invite code: configured / not configured" — never echo the raw code. After the trace-client extraction (5e568fc + 23104c9), the trace contribution code lives in crates/ironclaw_reborn_traces. The invite- code wiring lands on the extracted paths. Seven new unit tests, all green: - standing_policy_serde_back_compat_when_invite_code_missing - standing_policy_serde_round_trips_invite_code_when_set - standing_policy_serde_omits_invite_code_when_none - cache_key_distinguishes_different_invite_codes - parse_trace_upload_claim_error_label_handles_known_shapes - opt_in_invite_code_flag_parses_through_cli - opt_in_invite_code_defaults_to_none_when_absent
zmanian
added a commit
to nearai/ironclaw
that referenced
this pull request
May 23, 2026
Companion to TraceCommons/trace-commons#109 — the trace-commons server-side invite-code allowlist landed there with refusal labels PilotAllowlist* (NotMatched 403, InviteCodeMissing 400, Stale 503, Malformed 503). This commit teaches the Ironclaw trace client three things: 1. Carry the invite code through the standing policy. - StandingTraceContributionPolicy gains upload_token_invite_code: Option<String>, serde-default + skip-if- none so existing policy files keep parsing byte-identical. - TraceUploadClaimIssuerRequest body gains an optional invite_code field (forward-compat for a future server slice that may read it from the body in addition to the workload-JWT claim). - trace_upload_claim_cache_key keys on the invite code so a mid- pilot rotation forces a fresh claim mint. 2. Surface the typed allowlist refusal labels. fetch_trace_upload_claim_from_issuer now parses {"error": "<Label>"} bodies on non-success status and maps each PilotAllowlist* label to a user-actionable diagnostic. 3. CLI flag + status surface. ironclaw traces opt-in --upload-token-invite-code <CODE> (off by default). ironclaw traces status and queue-status report "pilot invite code: configured / not configured" — never echo the raw code. After the trace-client extraction (5e568fc + 23104c9), the trace contribution code lives in crates/ironclaw_reborn_traces. The invite- code wiring lands on the extracted paths. Seven new unit tests, all green: - standing_policy_serde_back_compat_when_invite_code_missing - standing_policy_serde_round_trips_invite_code_when_set - standing_policy_serde_omits_invite_code_when_none - cache_key_distinguishes_different_invite_codes - parse_trace_upload_claim_error_label_handles_known_shapes - opt_in_invite_code_flag_parses_through_cli - opt_in_invite_code_defaults_to_none_when_absent
zmanian
added a commit
to nearai/ironclaw
that referenced
this pull request
May 23, 2026
… CLI (#3738) * extract trace client into ironclaw_reborn_traces crate Move trace_contribution, trace_client, and tools/redaction into a new workspace crate so the standalone ironclaw_reborn_cli can consume them without depending on the monolith. The legacy src/trace_*.rs and src/tools/redaction.rs files remain as thin re-export shims so all existing call sites in the monolith continue to compile unchanged. ConversationMessage is now defined in the new crate; src/history/store.rs re-exports it so crate::history::ConversationMessage and the new ironclaw_reborn_traces::ConversationMessage are the same type. The single crate::bootstrap::ironclaw_base_dir() call inside contribution.rs is rewritten to call ironclaw_common::paths::ironclaw_base_dir directly. * add traces subcommand stub to ironclaw_reborn_cli Wire ironclaw_reborn_traces into the standalone reborn CLI and expose a minimal 'traces' subcommand with opt-in, status, and queue-status. The opt-in path prints a hand-off message pointing at the legacy ironclaw binary; status and queue-status call into ironclaw_reborn_traces using the anonymous scope so the wiring is exercised at compile time. The full TraceCommons CLI port lands separately. * wire pilot invite_code through upload-claim refresh Companion to TraceCommons/trace-commons#109 — the trace-commons server-side invite-code allowlist landed there with refusal labels PilotAllowlist* (NotMatched 403, InviteCodeMissing 400, Stale 503, Malformed 503). This commit teaches the Ironclaw trace client three things: 1. Carry the invite code through the standing policy. - StandingTraceContributionPolicy gains upload_token_invite_code: Option<String>, serde-default + skip-if- none so existing policy files keep parsing byte-identical. - TraceUploadClaimIssuerRequest body gains an optional invite_code field (forward-compat for a future server slice that may read it from the body in addition to the workload-JWT claim). - trace_upload_claim_cache_key keys on the invite code so a mid- pilot rotation forces a fresh claim mint. 2. Surface the typed allowlist refusal labels. fetch_trace_upload_claim_from_issuer now parses {"error": "<Label>"} bodies on non-success status and maps each PilotAllowlist* label to a user-actionable diagnostic. 3. CLI flag + status surface. ironclaw traces opt-in --upload-token-invite-code <CODE> (off by default). ironclaw traces status and queue-status report "pilot invite code: configured / not configured" — never echo the raw code. After the trace-client extraction (5e568fc + 23104c9), the trace contribution code lives in crates/ironclaw_reborn_traces. The invite- code wiring lands on the extracted paths. Seven new unit tests, all green: - standing_policy_serde_back_compat_when_invite_code_missing - standing_policy_serde_round_trips_invite_code_when_set - standing_policy_serde_omits_invite_code_when_none - cache_key_distinguishes_different_invite_codes - parse_trace_upload_claim_error_label_handles_known_shapes - opt_in_invite_code_flag_parses_through_cli - opt_in_invite_code_defaults_to_none_when_absent * migrate ironclaw traces CLI surface into ironclaw_reborn_cli Replaces the stub committed in 23104c9 with the full 50-subcommand implementation moved wholesale from src/cli/traces.rs. The monolith's ironclaw binary loses its traces subcommand; ironclaw-reborn traces ... becomes the only path. The library code remains in ironclaw_reborn_traces. Breaking CLI change: users invoking `ironclaw traces ...` must switch to `ironclaw-reborn traces ...`. Operator runbooks (pilot bootstrap, HF cache hygiene, GPU cost ledger) reference the legacy binary name and will need updating in a follow-up doc PR. * split traces CLI by audience into module tree * extract trace CLI tests into sibling tests.rs * prune operator commands from Ironclaw trace CLI Architectural pivot: Ironclaw's trace CLI holds only contributor-facing commands (consent, upload, credit display, monitoring). Operator commands (reviewer, worker, admin, tenant, audit) move out of Ironclaw entirely — they'll re-emerge as separate binaries in the trace-commons- server repo in a follow-up PR. Deleted 39 variants from TracesSubcommand and everything supporting them: handler fns, option structs, clap value enums, audience modules (reviewer.rs/worker.rs/admin.rs/tenant.rs), and tests. Kept 12 contributor variants: OptIn, OptOut, Status, Preview, Enqueue, FlushQueue, QueueStatus, Credit, Submit, ListSubmissions, Revoke, IngestHealth. All 7 invite-code tests continue to pass. * fix CI: cargo fmt + restore reborn-cli dep boundary Three CI failures on PR #3738: 1. cargo fmt --check diff in 15 spots across the traces module and tests. Ran cargo fmt --all to canonicalize. 2. reborn_crate_dependency_boundaries_hold + reborn_cli_binary_crate_stays_ separate_from_v1_root failed because the trace-client extraction added ironclaw_llm and ironclaw_common as direct deps of ironclaw_reborn_cli (the preview handler deserializes ironclaw_llm::recording::TraceFile, and the contribution dir resolver called ironclaw_common::paths::ironclaw_ base_dir). The architectural rule is that ironclaw_reborn_cli enters Reborn through the doorway crates only. Resolution: re-export both surfaces through ironclaw_reborn_traces: - ironclaw_reborn_traces::recording::* re-exports ironclaw_llm::recording - ironclaw_reborn_traces::paths::* re-exports ironclaw_common::paths Drop ironclaw_llm and ironclaw_common as direct deps of ironclaw_reborn_ cli. Add ironclaw_reborn_traces to the allowed-doorway set in the boundary test, with a doc comment explaining why (traces crate is the contributor-side TraceCommons client, analogous to composition + config). Final allowed deps of ironclaw_reborn_cli: ironclaw_reborn_composition, ironclaw_reborn_config, ironclaw_reborn_traces. No transitive leakage of ironclaw_llm / ironclaw_common into the binary's import surface. Verification: - RUSTFLAGS="-D warnings" cargo check --workspace --all-targets: clean - cargo fmt --all -- --check: clean - cargo test -p ironclaw_architecture --test reborn_dependency_boundaries: 19 passed - cargo test -p ironclaw_reborn_cli: 58 passed (invite-code tests included) - cargo clippy --workspace --all-targets -- -D warnings: clean * address PR #3738 review feedback - Enum-ify PilotAllowlist refusal labels (Medium-4). - Hash invite code in upload-claim cache key with sha256: prefix (Low-2). - show_policy_status treats whitespace-only invite code as not configured (Low-1). - Write policy.json with 0o600 permissions on unix (Medium-1). - Add caller-level tests for PilotAllowlist typed and generic error paths (High-1, High-2). - Add opt_in invite-code persistence test (Medium-2). - Add queue-status diagnostics invite-code-configured test (Medium-3). - Add parse_trace_upload_claim_error_label non-string coverage (Low-3).
theredspoon
pushed a commit
to theredspoon/ironclaw
that referenced
this pull request
Jun 21, 2026
… CLI (nearai#3738) * extract trace client into ironclaw_reborn_traces crate Move trace_contribution, trace_client, and tools/redaction into a new workspace crate so the standalone ironclaw_reborn_cli can consume them without depending on the monolith. The legacy src/trace_*.rs and src/tools/redaction.rs files remain as thin re-export shims so all existing call sites in the monolith continue to compile unchanged. ConversationMessage is now defined in the new crate; src/history/store.rs re-exports it so crate::history::ConversationMessage and the new ironclaw_reborn_traces::ConversationMessage are the same type. The single crate::bootstrap::ironclaw_base_dir() call inside contribution.rs is rewritten to call ironclaw_common::paths::ironclaw_base_dir directly. * add traces subcommand stub to ironclaw_reborn_cli Wire ironclaw_reborn_traces into the standalone reborn CLI and expose a minimal 'traces' subcommand with opt-in, status, and queue-status. The opt-in path prints a hand-off message pointing at the legacy ironclaw binary; status and queue-status call into ironclaw_reborn_traces using the anonymous scope so the wiring is exercised at compile time. The full TraceCommons CLI port lands separately. * wire pilot invite_code through upload-claim refresh Companion to TraceCommons/trace-commons#109 — the trace-commons server-side invite-code allowlist landed there with refusal labels PilotAllowlist* (NotMatched 403, InviteCodeMissing 400, Stale 503, Malformed 503). This commit teaches the Ironclaw trace client three things: 1. Carry the invite code through the standing policy. - StandingTraceContributionPolicy gains upload_token_invite_code: Option<String>, serde-default + skip-if- none so existing policy files keep parsing byte-identical. - TraceUploadClaimIssuerRequest body gains an optional invite_code field (forward-compat for a future server slice that may read it from the body in addition to the workload-JWT claim). - trace_upload_claim_cache_key keys on the invite code so a mid- pilot rotation forces a fresh claim mint. 2. Surface the typed allowlist refusal labels. fetch_trace_upload_claim_from_issuer now parses {"error": "<Label>"} bodies on non-success status and maps each PilotAllowlist* label to a user-actionable diagnostic. 3. CLI flag + status surface. ironclaw traces opt-in --upload-token-invite-code <CODE> (off by default). ironclaw traces status and queue-status report "pilot invite code: configured / not configured" — never echo the raw code. After the trace-client extraction (5e568fc + 23104c9), the trace contribution code lives in crates/ironclaw_reborn_traces. The invite- code wiring lands on the extracted paths. Seven new unit tests, all green: - standing_policy_serde_back_compat_when_invite_code_missing - standing_policy_serde_round_trips_invite_code_when_set - standing_policy_serde_omits_invite_code_when_none - cache_key_distinguishes_different_invite_codes - parse_trace_upload_claim_error_label_handles_known_shapes - opt_in_invite_code_flag_parses_through_cli - opt_in_invite_code_defaults_to_none_when_absent * migrate ironclaw traces CLI surface into ironclaw_reborn_cli Replaces the stub committed in 23104c9 with the full 50-subcommand implementation moved wholesale from src/cli/traces.rs. The monolith's ironclaw binary loses its traces subcommand; ironclaw-reborn traces ... becomes the only path. The library code remains in ironclaw_reborn_traces. Breaking CLI change: users invoking `ironclaw traces ...` must switch to `ironclaw-reborn traces ...`. Operator runbooks (pilot bootstrap, HF cache hygiene, GPU cost ledger) reference the legacy binary name and will need updating in a follow-up doc PR. * split traces CLI by audience into module tree * extract trace CLI tests into sibling tests.rs * prune operator commands from Ironclaw trace CLI Architectural pivot: Ironclaw's trace CLI holds only contributor-facing commands (consent, upload, credit display, monitoring). Operator commands (reviewer, worker, admin, tenant, audit) move out of Ironclaw entirely — they'll re-emerge as separate binaries in the trace-commons- server repo in a follow-up PR. Deleted 39 variants from TracesSubcommand and everything supporting them: handler fns, option structs, clap value enums, audience modules (reviewer.rs/worker.rs/admin.rs/tenant.rs), and tests. Kept 12 contributor variants: OptIn, OptOut, Status, Preview, Enqueue, FlushQueue, QueueStatus, Credit, Submit, ListSubmissions, Revoke, IngestHealth. All 7 invite-code tests continue to pass. * fix CI: cargo fmt + restore reborn-cli dep boundary Three CI failures on PR nearai#3738: 1. cargo fmt --check diff in 15 spots across the traces module and tests. Ran cargo fmt --all to canonicalize. 2. reborn_crate_dependency_boundaries_hold + reborn_cli_binary_crate_stays_ separate_from_v1_root failed because the trace-client extraction added ironclaw_llm and ironclaw_common as direct deps of ironclaw_reborn_cli (the preview handler deserializes ironclaw_llm::recording::TraceFile, and the contribution dir resolver called ironclaw_common::paths::ironclaw_ base_dir). The architectural rule is that ironclaw_reborn_cli enters Reborn through the doorway crates only. Resolution: re-export both surfaces through ironclaw_reborn_traces: - ironclaw_reborn_traces::recording::* re-exports ironclaw_llm::recording - ironclaw_reborn_traces::paths::* re-exports ironclaw_common::paths Drop ironclaw_llm and ironclaw_common as direct deps of ironclaw_reborn_ cli. Add ironclaw_reborn_traces to the allowed-doorway set in the boundary test, with a doc comment explaining why (traces crate is the contributor-side TraceCommons client, analogous to composition + config). Final allowed deps of ironclaw_reborn_cli: ironclaw_reborn_composition, ironclaw_reborn_config, ironclaw_reborn_traces. No transitive leakage of ironclaw_llm / ironclaw_common into the binary's import surface. Verification: - RUSTFLAGS="-D warnings" cargo check --workspace --all-targets: clean - cargo fmt --all -- --check: clean - cargo test -p ironclaw_architecture --test reborn_dependency_boundaries: 19 passed - cargo test -p ironclaw_reborn_cli: 58 passed (invite-code tests included) - cargo clippy --workspace --all-targets -- -D warnings: clean * address PR nearai#3738 review feedback - Enum-ify PilotAllowlist refusal labels (Medium-4). - Hash invite code in upload-claim cache key with sha256: prefix (Low-2). - show_policy_status treats whitespace-only invite code as not configured (Low-1). - Write policy.json with 0o600 permissions on unix (Medium-1). - Add caller-level tests for PilotAllowlist typed and generic error paths (High-1, High-2). - Add opt_in invite-code persistence test (Medium-2). - Add queue-status diagnostics invite-code-configured test (Medium-3). - Add parse_trace_upload_claim_error_label non-string coverage (Low-3).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements the pilot allowlist designed in #107 and planned in #108. Three slices, four commits, no new direct deps. Off-by-default — deployments that don't set `TRACE_COMMONS_ALLOWLIST_SOURCE` are byte-identical to pre-merge `main`.
` CLI subcommand uses the same `hash_invite_code` helper so the operator and the issuance handler can never drift. `docs/operator/pilot-allowlist.md` runbook, operator README index row, top-level README "Contributor gate" row.Refusal vocabulary
New env vars
`TRACE_COMMONS_ALLOWLIST_SOURCE`, `TRACE_COMMONS_ALLOWLIST_REFRESH_INTERVAL_SECONDS` (default 60), `TRACE_COMMONS_ALLOWLIST_MAX_STALE_SECONDS` (default 3600), `TRACE_COMMONS_ISSUER_ADMIN_BIND`, `TRACE_COMMONS_ISSUER_ADMIN_BIND_ALLOW_PUBLIC`.
Test plan
What's still deferred
What this doesn't touch