Skip to content

feat(agent): RSS-first production auth and workspace sessions - #4

Draft
fffonion wants to merge 169 commits into
masterfrom
feat/production-auth-workspace
Draft

fffonion wants to merge 169 commits into
masterfrom
feat/production-auth-workspace

Conversation

@fffonion

@fffonion fffonion commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Scope

Publishes the existing local RSS-first production-authentication stack without merging it into master.

  • RSS owns provider/auth/refresh/selection/default/source/workspace behavior; Rust supplies bounded credential, OS, transport and resource capabilities.
  • Includes the previously accepted local auth/provider and bundled-source work, the access-only Responses path, session/workspace admission, and packaged documentation corrections. The remote base predates these local commits, so this is the combined stack rather than a Task10-only diff.
  • Workspace effects use retained confined authority. Admission/replay comparisons and atomic storage eligibility remain in RSS; persisted paths never grant authority.
  • HTTP and Telegram workspace commands are followed by ordinary same-session runs with verified native file/process effects.
  • The new workspace replay identity preserves the original optional selector and permits pure cached/durable replay before reopening workspace authority.

Current verification

Functional candidate: c7e931eb776f28985bad9bb590029445a17d0db5.
Current PR head: 1d48f40d6c6cb4396a5ef23805c804bc72cd829d, adding only the formatting repair requested by the first CI format check (one optional trailing argument comma removed, no argument/expression/assertion change). Local cargo fmt --all -- --check and a fresh current-artifact config_file_tests execution (21/21) passed after this repair. The initial remote CI failure and its subsequent rerun are kept distinct; no remote CI success is claimed here.

The subsequent CI run (https://github.com/rustscript-lang/rustscript-agent/actions/runs/38096048015) passed Format check, then failed Clippy (warnings denied) on clippy::collapsible_match at src/auth/authorization_output.rs:326. Its all-feature/all-target test step was skipped. This additional CI failure remains open; it must not be confused with the independently recorded lifecycle baseline failures below.

Final current-candidate execution used current-manifest Cargo JSON artifacts, exact feature/source checks, direct inner return codes, sequential builds and default-parallel test execution:

  • 23 scoped gates: 22 passed; the full lifecycle target is separately qualified below.
  • Documentation consistency: 9/9; documentation drift: 9/9; typed HTTP migration: 14/14.
  • fmt, Clippy (-D warnings) and diff checks passed.
  • Real RSS source discovery/corpus compilation passed; compile coverage is recorded separately from runtime acceptance.
  • Narrow independent review closed original S2/S3/S5 and the two documentation compatibility regressions.
  • New-format S1 cached/durable replay was covered. An additional independent compatibility probe used the exact supported-main 19603db0ff62527cb1ff1aa66f375ef98d7b06fc RSS storage writer with private business SQLite and reopened it using the current consumer: the same request returned the original run, with no new messages/events; adding a selector was rejected.

Known failing target

Full run_lifecycle_tests returned RC 101: 32 passed, 2 failed:

  • hanging_http_adapter_stop_cancels
  • test_sources_do_not_hardcode_sibling_lease_temp_roots

Both failures were independently classified against the prior base; they remain recorded and are not reported as target success. Original assertions, timing limits, process cleanup and admission bounds were retained. A historical transient pending-count observation race is also retained as an existing advisory; later passing runs do not erase it.

Compatibility qualification

The narrow reviewer raised a conditional S1 concern about reusing the old workspace-scoped idempotency format from unaccepted candidate b8d46bd75db108bfba911f8e49a0c03ac02e5533. That prerelease format has not been integrated into master or deployed in this execution and is not treated as a supported deployed format. Supported-main compatibility was exercised separately as described above. No legacy native business-hash implementation was introduced.

Remaining work

This is a draft integration PR, not a completed release:

  • Task11: production approval decisions and execution gating.
  • Task12: production compaction wiring.
  • Task13: remaining migration/release integration and final full-suite acceptance.
  • Task8: full live refresh validation is deferred; the accepted live path used access tokens only.

No auto-merge is enabled. The PR does not claim all debug/release suites or whole-plan completion.

hermes-agent and others added 30 commits October 10, 2026 01:06
Add std-only build.rs that recursively discovers the tracked rss/ tree,
excludes only the three exact default-corpus fixtures, sorts original
rss/... keys, and emits a generated &[(&str, &str)] catalog whose values
are compile-time include_str! of each asset's absolute path. Expose
bundled_rss_sources via a private module + public re-export in lib.rs.

Guards (before code emission): regular files only (no symlinks), UTF-8
paths, canonical rss-root confinement, no traversal/control/backslash/empty
components; bounds match the module snapshot (256 files, depth 16, 1 MiB
per file, checked 8 MiB total). No runtime source/fs/env reopening, no
hashes, no subprocess/git/network.

Tests execute the real source_policy.rss through the Core VM at an absent
virtual root (default, Unicode legacy precedence, invalid authority),
bind catalog bytes to the tracked tree, and qualify the coding main entry
from embedded overrides both in-checkout and from a source-free child cwd.

Placeholder RED (compilable failure scaffold, business-output mismatch) ->
actual include_str! GREEN -> complete generated inventory, all preserved.
Move the auth-only in-memory bundle admission/compiler into a shared
crate-internal src/runtime/closed_bundle.rs with a parameterized
ClosedBundle API (limits/catalog/dialect/virtual_root/host_roots/
entry_export). auth_runner/bundle.rs becomes a thin wrapper preserving
the original 64-file/16-depth/1MiB-per-file/4MiB-total limits, auth
host roots, JSON builtin, entry export, and error mapping. Adds focused
native-boundary unit tests covering supplied smaller limits, alternate
virtual root/catalog namespace, and exact root-symbol export selection
with real Vm execution.
Route the actual bundled-resource runtime consumers through the embedded
immutable catalog (rss/... original keys) instead of live filesystem reads:

- closed_bundle: add a bounded catalog closure selector over the whole
  immutable catalog reusing the existing validate_bundle_path/scan_imports/
  resolve_bundle_import + host-namespace clause check (no new resolver). Add a
  bundled-only compile entry that shares the EXISTING compiler/admission body
  with the original entry; only the bundled route parses modules under the
  catalog-derived implicit-externs parse context. compile_closed_bundle and
  ClosedBundleOptions are unchanged for the accepted auth caller.
- module_snapshot: mechanically extract the existing sorted length-prefixed
  files+entry digest body into a crate-private owned-memory snapshot
  constructor; expose the existing snapshot dialect crate-internally.
- rss_runner: public AgentRunner::from_bundled / from_bundled_named and
  crate-private bundled_resource_key; sealed private origin metadata (resource
  key/logical export/exact root callable); bundled programs cached only in the
  existing bounded ProgramLru under a "bundled:" identity domain; host roots
  derived from the same agent catalog (plus the json/bytes parser-builtin gap).
  prepare_vm binds only the recorded logical export to the exact root callable.
  Consumers migrated: load_bundled_tool_registry, default provider dispatch and
  with_host prewarm, StorageRunner::open. Legacy from_source/from_file and the
  bundled_agent_main_path helper are unchanged.
- gateway/store: StorageRunner::open uses from_bundled("rss/storage/main.rss").
- tests: new bundled_resource_runtime_tests.rs drives real bundled Main through
  a scripted provider, the bundled default dispatcher with injected native auth,
  and the bundled storage worker against assigned TEMP SQLite.

No Core/RSS/manifest/lib/service/gateway-policy/config/skills/grant changes.
Wire the dependency-sealed bundled arm now that the native closed-bundle API is
available:

- gateway: with_agent_selection BundledCoding compiles rss/agent/main.rss via
  AgentRunner::from_bundled and installs it through the tagged bundled route;
  new()/with_sqlite_path() route an empty selection through the RSS policy.
- service: private tagged AgentEntry File/Bundled. The bundled cache honors a
  hit only for the same admitted key and effective config, else recompiles the
  same key through the native API and never reads the checkout module tree. The
  File branch keeps the original live-tree freshness/retries/hooks unchanged.
  install_bundled_agent_entry compiles with the current effective config before
  publishing the tag.
- bin: RUSTSCRIPT_AGENT_SOURCE/PD_EDGE_AGENT_SOURCE (plus legacy script names)
  collected raw into the selection map; state is built before listener bind and
  an invalid authoritative source never falls back.
- api_server: bounded {kind,hash,deprecated_override} source facts from the
  admitted native runner snapshot digest.
- tests/packaging_startup_tests.rs: generated-policy decisions, the bundled
  tracer, file-consumption/health, and real-binary loopback health + pre-listen
  gates.
The gateway startup collector forwarded a present-but-non-UTF8
RUSTSCRIPT_AGENT_SOURCE / legacy RUSTSCRIPT_AGENT_SCRIPT token as
`env::VarError::NotUnicode`, whose Debug form (`NotUnicode("\xFF...")`)
leaked the raw OS bytes before the RSS source policy could classify the
value.

Add a small private `source_env_value` helper that wraps the existing
`env_value` collector for exactly the two selected source fields: valid
UTF8 tokens pass through verbatim and a missing token still omits the map
field, while a present non-UTF8 token is admitted as the fixed public
boolean `false`. The RSS source policy then observes a present non-string
value and owns the invalid/static classification, priority, and
no-fallback decision (a present non-string source is invalid without a
legacy fallback; a valid authoritative source ignores an unused invalid
legacy token). No raw byte, repair, or Rust-side business policy is added;
every other collector stays unchanged.

Two actual-binary packaging regressions cover the non-UTF8 SOURCE
(with a valid legacy) static-invalid pre-listen case and the valid SOURCE
(valid bundled) with an unused non-UTF8 legacy case; both RED against the
unfixed binary and GREEN after this change.
The default provider fails closed statically before dispatch when no native
auth host factory is installed, reporting canonical auth_unavailable and the
static 'native auth host is unavailable for default provider' message. Update
only the two obsolete expected strings in the SSE terminal-event case; event
order, run/agent_failed terminal code, run_id, status, headers, size bound and
budgets are unchanged.
Stage the six normalized tables (sessions, runs, jobs, idempotency_records,
messages, run_events) into connection-local immutable TEMP snapshots inside
one bounded sqlite::transaction batch before any page projection, so a writer
committing on another connection mid-load can no longer tear the dump. Every
stage object is TEMP-qualified (temp.load_stage_*), so a colliding main-table
name is never inspected, shadowed, or deleted. The original 512-row/2MiB page
bounds, typed load_cap overflow, and 5s transaction/30s worker ceilings are
unchanged. Adds a controlled cross-connection read-coherence regression
(shipped loader instrumented with a single emit barrier, run in a bounded
rescue helper process) and a main-table collision regression.
- deployment.md: quote the Cargo.toml-pinned core revision (d9387f98…) and
  the real binary set; document the authoritative RUSTSCRIPT_AGENT_SOURCE
  selection and its pre-listen static failures.
- configuration.md: correct the false 'production lacks the config bridge'
  claim (auth_host_module registers config::load_snapshot); document
  RUSTSCRIPT_AGENT_SOURCE / deprecated RUSTSCRIPT_AGENT_SCRIPT semantics and
  qualify RUSTSCRIPT_AGENT_TEST_TMP as a non-production internal test input.
- docs/examples: bounded empty-credential config.yaml/auth.yaml loader sample.
- tests/documentation_consistency_tests.rs: source-derived guards for the pin,
  binary set, source-selection semantics, config bridge, internal test input,
  example loader decoding, and real RSS effective_selection over the example.
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