Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,19 @@ jobs:
- run: uv python install 3.13
- run: make install
- run: make db-up
- run: make check
- name: Run complete checks including the M0 security gate
id: complete-checks
run: make check
- name: Retain M0 security gate evidence
if: always()
uses: actions/upload-artifact@v4
with:
name: m0-security-gate-${{ github.sha }}
path: |
.context-engine/security-gate/raw-evidence.json
.context-engine/security-gate/release-gate-report.json
include-hidden-files: true
if-no-files-found: error
retention-days: 30
- if: always()
run: make db-down
7 changes: 6 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ make lint # Ruff
make typecheck # strict mypy
make test # unit test suite
make catalog # static security catalog tests and validation
make security-gate # executable M0 security veto; requires make db-up first
make smoke # API and worker process smoke suite
make db-up # start the real PostgreSQL 17 + pgvector harness
make db-down # stop the harness while preserving its disposable data volume
Expand All @@ -77,7 +78,11 @@ ignored, mode-0600 source for local database connection contracts; `compose.yaml
owns the pinned test service topology. A green process smoke proves only
boot/readiness. The database harness additionally proves Organization, current
Membership, the online UserActor transaction, and representative-record FORCE-RLS
isolation. Content-bearing Runtime delivery and worker-job behavior remain
isolation. `make security-gate` executes the registered M0 evidence and writes
raw evidence plus its independent release-gate report beneath the ignored
`.context-engine/security-gate/` directory. Content-bearing Runtime delivery
and worker-job behavior are active only for the exact carriers recorded by
their accepted catalog activations; deferred carrier semantics remain
`NOT_ACTIVE` until their owning issues verify them.

## Safety-Rails / Do Not
Expand Down
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: install build lint typecheck test catalog smoke db-up db-down db-reset integration check
.PHONY: install build lint typecheck test catalog security-gate smoke db-up db-down db-reset integration check

install:
uv sync --frozen
Expand All @@ -19,6 +19,9 @@ catalog:
uv run pytest -q tests/catalog
uv run python scripts/validate_security_catalog.py

security-gate:
uv run python scripts/run_m0_security_gate.py --output-dir .context-engine/security-gate

smoke:
uv run pytest -q tests/process

Expand All @@ -34,4 +37,4 @@ db-reset:
integration:
./scripts/database_harness.sh integration

check: build lint typecheck test catalog smoke integration
check: build lint typecheck test catalog smoke integration security-gate
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ make lint # Ruff
make typecheck # strict mypy
make test # 单元测试
make catalog # 安全目录静态测试与校验
make security-gate # 可执行 M0 安全否决门;要求先执行 make db-up
make smoke # API / worker 进程 smoke
make db-up # 启动 compose.yaml 固定的 PostgreSQL + pgvector 测试底座
make db-down # 停止测试底座并保留 disposable data volume
Expand All @@ -58,6 +59,12 @@ make integration # 真实 PostgreSQL integration/security harness
make check # 全部门禁;要求先执行 make db-up
```

`make security-gate` 会发现并只执行注册的 M0 安全证据,核对真实 PostgreSQL
RLS inventory,并将机器可读的原始证据与四门 release report 写入被 Git 忽略的
`.context-engine/security-gate/`。Security 是独立否决门;尚未进入 M0 评估范围的
Reliability、Quality 与 Budget 明确记录为 `not-evaluated`,所以这份报告只会给出
`m0SecurityDecision`,不会把安全门通过误写成可发布或可 promotion 的总体 PASS。

数据库底座首次启动时会在被 Git 忽略的
`.context-engine/database.env` 生成随机凭据并将文件权限设为 `0600`;该文件是
本地 migration、API Runtime、worker、security test 连接配置和该 checkout
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
name: adr-0034-executable-m0-security-veto
version: "1.0.0"
description: >
Join the frozen security authority to exact executable evidence, live RLS
inventory, and provenance-bearing release artifacts without inventing
product behavior or aggregate scoring.
---

# 0034. Execute the M0 security veto from registered evidence

- Status: accepted
- Date: 2026-07-22
- Refines: ADR-0015, ADR-0019

## Context

The normalized security catalog fixes fifteen invariant families and twelve
acceptance fixtures, including the expected fail-closed outcome for carriers
that are not active at M0. Its evidence identifiers intentionally describe the
full delivery roadmap. They are design authority, but a string in that catalog
does not prove that a current test exists, was collected, ran without a skip,
or passed against the required seam.

The schema security manifest is likewise the declared table-classification
authority. Reading only its `rls.enabled` fields would let drift in the live
database, a newly unclassified table, or removed `FORCE ROW LEVEL SECURITY`
escape a release report. Finally, reducing Security, Reliability, Quality, and
Budget to one score would allow an unrelated result to offset a failed
authorization invariant.

## Decision

The static security catalog remains the semantic authority. A separate,
versioned M0 evidence registry joins current evidence identifiers to exact
pytest selectors, one evidence class (`property`, `postgres`, or `runtime`),
the invariant families genuinely proved, and the acceptance fixtures whose
explicit observations they emit. The registry must cover every invariant in
all three evidence classes and every canonical fixture. Duplicate identifiers,
unknown references, empty or missing mappings, uncollected selectors, skips,
xfails, xpasses, and failed setup, call, or teardown outcomes are deterministic
Security failures. Registered selectors are de-duplicated and executed once;
the gate has no retry path.

Fixture tests publish the three hard-oracle observations rather than relying
on pytest success as a substitute for measurement: unauthorized Evidence,
wrong-Organization effect, and missing-context fallback. Every required value
is zero. A missing or non-zero observation fails Security and the command.
Inactive M0 carriers are tested at their current public fail-closed boundary;
the gate does not add their future product semantics.

The schema security manifest is the complete public-table denominator. Each
table is exactly one of `tenant_owned` or explicitly allowlisted `global`, and
each global entry carries a non-empty rationale. For every tenant-owned table,
the gate verifies a machine-declared Organization ownership path, enabled and
forced live RLS, at least one live policy, and registered non-owner PostgreSQL
evidence. It first requires the live public-table set to equal the manifest, so
an unclassified table cannot disappear from the denominator. Coverage is
reported per table and as numerator over denominator; M0 requires complete
coverage.

One local and CI command performs static validation, exact evidence execution,
the live PostgreSQL audit, and report generation. It writes canonical raw
evidence plus a release-gate report. Provenance includes the Git commit and
tracked-worktree state, catalog/registry/schema/configuration digests, Alembic
head and live revision, exact execution command, and a deterministic digest of
normalized test outcomes and observations. Wall-clock durations remain in raw
evidence but are excluded from that normalized result digest. Provenance never
records database URLs or credentials.

The release report has four independent sections: Security, Reliability,
Quality, and Budget. Security is `pass` or `fail` and is a veto. The other
three are explicitly `not-evaluated` at M0 until their owning gates exist;
`not-evaluated` is never converted to pass. The document has no aggregate
score, weighted score, or averaging field. A passing Security section sets only
`m0SecurityDecision: pass`; `releaseDecision` and `promotionReadiness` remain
`not-evaluated`, so this integration report is not a promotion-ready
`ReleaseEvaluation`.

## Rationale

Separating expected roadmap evidence from the executable registry preserves
stable design identifiers while making the current proof discoverable and
strict. Exact pytest collection closes the gap between a referenced test name
and an executed assertion. Explicit observations prevent the runner from
manufacturing hard-oracle zeros from a green process exit.

Using the manifest as the denominator and PostgreSQL catalogs as live facts
makes complete RLS coverage measurable without guessing from column names.
Keeping the four gates independent preserves the Security veto and represents
unevaluated work honestly.

## Consequences

Adding or renaming a registered test, invariant, fixture, or application table
requires an intentional registry or manifest update. A deterministic skip is a
red gate, not a temporary green build. Registered evidence may support multiple
families only when its registry references and assertions name each proof.

The executable gate re-runs a focused subset after the broad unit and
integration suites so it can retain exact release evidence. That extra runtime
is accepted for M0. Generated artifacts remain ignored locally and are retained
by CI; they are evidence, not source authority.

## Revisit trigger

Revisit the registry transport if pytest is replaced or signed remote evidence
becomes necessary. Revisit the three unevaluated sections only when their
independent deterministic commands and provenance contracts exist. Any
replacement must still execute all canonical mappings without skips or retries,
derive hard-oracle results from explicit observations, audit the complete live
RLS denominator, retain raw evidence, and preserve Security as a non-aggregate
veto.
2 changes: 2 additions & 0 deletions docs/decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ kernel, capability separation, and publication visibility model.
| Release promotion owner | [0033 — Organization release promotion owner](0033-promote-organization-releases-through-one-learning-owner.md) | Organization-owned immutable release lineage advances only through one generation-bound, release-operator-authorized `ContextLearning.promote` transaction | Pointer seeds, direct application DML, manifest-only CAS, evaluator/Control/Curation publication, or rollback mutation |
| Publication visibility | [0018 — Immutable ContextRevision publication](0018-immutable-revision-publication.md) | `ContextResource` content is immutable `ContextRevision`/`ContextFragment` lineage; one transaction changes the active pointer | In-place content mutation, mixed old/new reads, or cleanup-defined visibility |
| Release security catalog | [0019 — Security catalog normalization](0019-security-catalog-normalization.md) | One machine catalog contains exactly fifteen stable release IDs; overlapping labels and derived scenarios keep their safeguards without inflating the count | Parallel prose catalogs, renumbering, or treating inactive cache behavior as a canonical release family |
| Executable M0 security veto | [0034 — Registered executable security evidence](0034-execute-the-m0-security-veto-from-registered-evidence.md) | Exact current tests, explicit hard-oracle observations, and live all-table RLS facts produce provenance-bearing independent gate artifacts | Planned IDs presented as executed proof, skip/retry-to-green, manifest-only RLS claims, or aggregate scoring |

Each baseline ADR is `accepted` and contains Context, Decision, Rationale,
Consequences, and Revisit trigger sections. A revisit trigger permits review; it
Expand Down Expand Up @@ -115,3 +116,4 @@ touched:
- [0031 — Authorized-only ContextRun lineage](0031-persist-authorized-context-run-lineage.md)
- [0032 — Membership-bound materialized fields](0032-bind-materialized-fields-to-membership-projection-rights.md)
- [0033 — Organization release promotion owner](0033-promote-organization-releases-through-one-learning-owner.md)
- [0034 — Registered executable security evidence](0034-execute-the-m0-security-veto-from-registered-evidence.md)
Loading
Loading