Skip to content

ACE-040: safety regression corpus — the F9 done-bar#121

Open
sandeep-agami wants to merge 1 commit into
ACE-039-recon-error-hardeningfrom
ACE-040-safety-regression-corpus
Open

ACE-040: safety regression corpus — the F9 done-bar#121
sandeep-agami wants to merge 1 commit into
ACE-039-recon-error-hardeningfrom
ACE-040-safety-regression-corpus

Conversation

@sandeep-agami

Copy link
Copy Markdown
Collaborator

Summary

Spec: ACE-040 — the F9 done-bar. One adversarial safety regression corpus that drives every attack class through the REAL execute_sql tool and asserts its expected Envelope, on both surfaces (stdio subprocess + in-process HTTP) and both model paths (file-served: SQLite + disk YAML; DB-served: Postgres + model_store), plus a read-only role floor that proves the DB rejects a write with the app gate bypassed. This is the regression bar a future change must not drop below. Test-only + CI — no src changes; it locks the controls built in ACE-035…039.

Stacked on #120 (ACE-039) — base is ACE-039-recon-error-hardening; retarget to main once the stack lands.

Changes

  • tests/safety/corpus.py — the single canonical source: the demo SCHEMA (the harness derives BOTH the semantic model and the physical datasource from it) + CASES mapping each class to its outcome. Classes: integrity→permission, object-scope→table_out_of_scope/select_star/column_out_of_scope (incl. hidden in UNION/EXCEPT arms), fail-closed→unscopable_sql, recon→recon, availability→bounded (row-cap truncate+flag), governed→ok (no false refusals).
  • tests/e2e/harness.py — ONE copy of the stdio + HTTP drivers + the model/datasource builders (test_safety_envelope.py now imports them — drivers single-sourced, no duplication).
  • tests/e2e/conftest.pysurface (stdio|http) + file_safety_env + the Postgres fixtures (pg_admin, create_ro_role, db_safety_env, pg_ro_conn).
  • tests/e2e/test_safety_corpus.py — the corpus over {surface} × {file, DB} paths.
  • tests/e2e/test_role_floor_pg.py — writes on a RAW agami_ro connection (app gate bypassed) → Postgres raises InsufficientPrivilege; a SELECT succeeds.
  • .github/workflows/ci.yml — a new integration-pg job (a postgres:16 service — the repo's first CI service) runs the DB-dependent tests; an AGAMI_IT_PG_REQUIRED sentinel makes an unavailable DB fail (not skip) so an all-skip can't pass green.

Verification

  • File path (local): greenuv run dev.py check passes; 58 corpus cases (29 × both surfaces) + the envelope tests. Full suite 1752 passed / 62 skipped.
  • Postgres path (local): skips — no Docker on this machine, so the DB-served corpus + role-floor skip cleanly locally; the integration-pg CI job is their first real run. The fixtures were written against the compose fixture's known creds and read as if debugging; a focused security review traced the guard order per case, confirmed the role-floor genuinely bypasses the app gate, and confirmed the corpus is non-vacuous (a regressed control degrades each case to a failure, never a silent pass).

Reviewer notes / follow-ups

  1. Make integration-pg a required check (branch protection — outside this diff). The sentinel guarantees it can't pass green on an all-skip, but it must actually be required to gate merges.
  2. PG path is first-run-in-CI (no local Docker here) — worth a close look at the first integration-pg run.
  3. High-lane → security sign-off required per the spec.
  4. Consolidation is additive (per sign-off): the corpus is the new end-to-end bar + single-sourced vectors; the existing ~15 unit gate-tests stay as the fine-grained layer (full retire is a follow-up).

Checklist

  • Spec: ACE-040 on every commit; diff stays in spec scope (declined a PII/sensitive_columns case — spec assigns PII to F10's corpus)
  • Both surfaces + both paths exercised and asserted identically
  • No weakened/deleted tests; the one refactor (shared drivers) keeps test_safety_envelope.py green
  • uv run dev.py check green (file path); review dispositioned (1 must-fix fixed)
  • integration-pg green in CI (first run) + made a required check

🤖 Generated with Claude Code

@gitguardian

gitguardian Bot commented Jul 13, 2026

Copy link
Copy Markdown

️✅ There are no secrets present in this pull request anymore.

If these secrets were true positive and are still valid, we highly recommend you to revoke them.
While these secrets were previously flagged, we no longer have a reference to the
specific commits where they were detected. Once a secret has been leaked into a git
repository, you should consider it compromised, even if it was deleted immediately.
Find here more information about risks.


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

One adversarial corpus that locks every F9 control: it drives each attack class through the REAL
execute_sql tool and asserts its expected Envelope, on BOTH surfaces (stdio subprocess + in-process
HTTP) and BOTH model paths (file-served: SQLite + disk YAML; DB-served: Postgres + model_store), plus
a read-only role FLOOR that proves the database rejects a write with the app gate bypassed. Test-only
+ CI; it locks the controls built in ACE-035..039 (does not change them).

- tests/safety/corpus.py — the single canonical source: the demo SCHEMA (the harness derives BOTH the
  semantic model and the physical datasource from it) + CASES mapping each class to its outcome.
  Classes: integrity→permission, object-scope→table_out_of_scope/select_star/column_out_of_scope
  (incl. hidden in UNION/EXCEPT arms), fail-closed→unscopable_sql, recon→recon, availability→bounded
  (row-cap truncate+flag), governed→ok (no false refusals).
- tests/e2e/harness.py — ONE copy of the stdio + HTTP drivers + the model/datasource builders
  (test_safety_envelope.py imports them; drivers single-sourced, no duplication).
- tests/e2e/conftest.py — surface (stdio|http) + file_safety_env + the Postgres fixtures
  (pg_admin with an AGAMI_IT_PG_REQUIRED sentinel so an all-skip can't pass green, create_ro_role,
  db_safety_env, pg_ro_conn). Serial-only (shared role/table); the role password is derived from env.
- tests/e2e/test_safety_corpus.py — the corpus over {surface} × {file, DB} paths.
- tests/e2e/test_role_floor_pg.py — writes on a RAW agami_ro connection (app gate bypassed) →
  Postgres raises InsufficientPrivilege; a SELECT succeeds.
- .github/workflows/ci.yml — a new integration-pg job (a postgres:16 service, trust auth — no
  password literal) runs the DB-dependent tests; the sentinel makes an unavailable DB fail, not skip.

Consolidation is additive (per sign-off): the corpus is the new end-to-end bar + single-sourced
vectors; the existing unit gate-tests stay as the fine-grained layer. Reviewed (1 must-fix fixed,
nits dispositioned). File path verified green locally; the Postgres path is first-run-in-CI (no local
Docker). Make integration-pg a required check.

Spec: ACE-040

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sandeep-agami
sandeep-agami force-pushed the ACE-040-safety-regression-corpus branch from 1accd3f to c8cb377 Compare July 13, 2026 05:06
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