orion-verify 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. orion_verify-0.5.0/.env.example +16 -0
  2. orion_verify-0.5.0/.github/workflows/build-package.yml +25 -0
  3. orion_verify-0.5.0/.github/workflows/ci.yml +42 -0
  4. orion_verify-0.5.0/.github/workflows/publish-pypi.yml +64 -0
  5. orion_verify-0.5.0/.gitignore +12 -0
  6. orion_verify-0.5.0/ANNOUNCEMENT.md +15 -0
  7. orion_verify-0.5.0/API_REFERENCE.md +77 -0
  8. orion_verify-0.5.0/ARCHITECTURE.md +49 -0
  9. orion_verify-0.5.0/CHANGELOG.md +38 -0
  10. orion_verify-0.5.0/CONTRIBUTING.md +40 -0
  11. orion_verify-0.5.0/Codes.md +363 -0
  12. orion_verify-0.5.0/Dockerfile +11 -0
  13. orion_verify-0.5.0/IMAGES.md +26 -0
  14. orion_verify-0.5.0/LICENSE +9 -0
  15. orion_verify-0.5.0/PKG-INFO +257 -0
  16. orion_verify-0.5.0/README.md +222 -0
  17. orion_verify-0.5.0/RELEASE_CHECKLIST.md +52 -0
  18. orion_verify-0.5.0/SECURITY.md +60 -0
  19. orion_verify-0.5.0/SECURITY_AUDIT.md +89 -0
  20. orion_verify-0.5.0/THREAT_MODEL.md +47 -0
  21. orion_verify-0.5.0/code.md +5 -0
  22. orion_verify-0.5.0/deploy/docker-compose.yml +28 -0
  23. orion_verify-0.5.0/examples/extensions/orion-antispam/antispam.py +70 -0
  24. orion_verify-0.5.0/examples/extensions/orion-antispam/extension.json +6 -0
  25. orion_verify-0.5.0/pyproject.toml +57 -0
  26. orion_verify-0.5.0/src/orion_verify/__init__.py +7 -0
  27. orion_verify-0.5.0/src/orion_verify/app.py +286 -0
  28. orion_verify-0.5.0/src/orion_verify/cli.py +152 -0
  29. orion_verify-0.5.0/src/orion_verify/client.py +65 -0
  30. orion_verify-0.5.0/src/orion_verify/client_connect.py +35 -0
  31. orion_verify-0.5.0/src/orion_verify/config.py +67 -0
  32. orion_verify-0.5.0/src/orion_verify/db.py +56 -0
  33. orion_verify-0.5.0/src/orion_verify/extensions.py +166 -0
  34. orion_verify-0.5.0/src/orion_verify/models.py +48 -0
  35. orion_verify-0.5.0/src/orion_verify/security.py +36 -0
  36. orion_verify-0.5.0/src/orion_verify/server_connect.py +42 -0
  37. orion_verify-0.5.0/src/orion_verify/service.py +299 -0
  38. orion_verify-0.5.0/src/orion_verify/widget.js +86 -0
  39. orion_verify-0.5.0/test.py +179 -0
  40. orion_verify-0.5.0/tests/conftest.py +9 -0
  41. orion_verify-0.5.0/tests/test_antispam_extension.py +34 -0
  42. orion_verify-0.5.0/tests/test_app.py +55 -0
  43. orion_verify-0.5.0/tests/test_cli.py +50 -0
  44. orion_verify-0.5.0/tests/test_client.py +22 -0
  45. orion_verify-0.5.0/tests/test_connect.py +35 -0
  46. orion_verify-0.5.0/tests/test_demo.py +66 -0
  47. orion_verify-0.5.0/tests/test_extensions.py +41 -0
  48. orion_verify-0.5.0/tests/test_security.py +16 -0
  49. orion_verify-0.5.0/tests/test_service.py +155 -0
  50. orion_verify-0.5.0/widget/widget.js +86 -0
@@ -0,0 +1,16 @@
1
+ # Use a unique 64-character hex secret in production: python -c "import secrets; print(secrets.token_hex(32))"
2
+ ORION_DATABASE_URL=postgresql+psycopg://orion:CHANGE_TO_URL_SAFE_PASSWORD@127.0.0.1:5432/orion
3
+ ORION_MASTER_SECRET=REPLACE_WITH_64_HEX_CHARACTERS
4
+ ORION_ADMIN_SECRET=REPLACE_WITH_RANDOM_SECRET
5
+ ORION_IP_DAILY_TOKEN_LIMIT=30
6
+ ORION_IP_DAILY_CHALLENGE_LIMIT=120
7
+ ORION_POW_DIFFICULTY_BITS=16
8
+ ORION_CHALLENGE_TTL_SECONDS=120
9
+ ORION_TOKEN_TTL_SECONDS=120
10
+ ORION_MAX_ACTIVE_KEYS=3
11
+ # Defaults to loopback-only. Add only trusted management IP/CIDR entries if needed.
12
+ ORION_ADMIN_ALLOWED_CIDRS=127.0.0.1/32,::1/128
13
+ # Leave empty unless a reverse proxy is explicitly trusted and overwrites/appends X-Forwarded-For safely.
14
+ ORION_TRUSTED_PROXY_CIDRS=
15
+ ORION_MAX_REQUEST_BYTES=16384
16
+ ORION_DNS_TIMEOUT_SECONDS=3.0
@@ -0,0 +1,25 @@
1
+ name: Build package
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ tags: ["v*"]
6
+ pull_request:
7
+ workflow_dispatch:
8
+ permissions:
9
+ contents: read
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v5
15
+ - uses: actions/setup-python@v6
16
+ with:
17
+ python-version: "3.12"
18
+ - run: python -m pip install --upgrade pip build twine
19
+ - run: python -m build
20
+ - run: python -m twine check dist/*
21
+ - uses: actions/upload-artifact@v5
22
+ with:
23
+ name: orion-model-dist
24
+ path: dist/*
25
+ if-no-files-found: error
@@ -0,0 +1,42 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+ workflow_dispatch:
7
+ permissions:
8
+ contents: read
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ python-version: ["3.11", "3.12", "3.13"]
16
+ services:
17
+ postgres:
18
+ image: postgres:16
19
+ env:
20
+ POSTGRES_USER: orion
21
+ POSTGRES_PASSWORD: test-password
22
+ POSTGRES_DB: orion
23
+ ports: ["5432:5432"]
24
+ options: >-
25
+ --health-cmd "pg_isready -U orion -d orion"
26
+ --health-interval 10s --health-timeout 5s --health-retries 5
27
+ env:
28
+ ORION_DATABASE_URL: postgresql+psycopg://orion:test-password@localhost:5432/orion
29
+ ORION_MASTER_SECRET: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
30
+ ORION_ADMIN_SECRET: ci-only-admin-secret
31
+ steps:
32
+ - uses: actions/checkout@v5
33
+ - uses: actions/setup-python@v6
34
+ with:
35
+ python-version: ${{ matrix.python-version }}
36
+ cache: pip
37
+ - run: python -m pip install --upgrade pip
38
+ - run: python -m pip install -e '.[test,postgres]' build twine
39
+ - run: python -m compileall -q src tests
40
+ - run: pytest -q
41
+ - run: python -m build
42
+ - run: python -m twine check dist/*
@@ -0,0 +1,64 @@
1
+ name: Publish to PyPI (manual release gate)
2
+ on:
3
+ workflow_dispatch:
4
+ inputs:
5
+ version_tag:
6
+ description: Existing version tag to build, e.g. v0.5.0
7
+ required: true
8
+ type: string
9
+ confirm_publish:
10
+ description: Confirm that tests, package name, metadata, ownership proof and release review have passed
11
+ required: true
12
+ default: false
13
+ type: boolean
14
+ permissions:
15
+ contents: read
16
+ jobs:
17
+ build:
18
+ if: ${{ inputs.confirm_publish == true }}
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v5
22
+ with:
23
+ ref: ${{ inputs.version_tag }}
24
+ - uses: actions/setup-python@v6
25
+ with:
26
+ python-version: "3.12"
27
+ - run: python -m pip install --upgrade pip build twine
28
+ - run: python -m build
29
+ - run: python -m twine check dist/*
30
+ - name: Verify tag matches package version
31
+ env:
32
+ RELEASE_TAG: ${{ inputs.version_tag }}
33
+ run: |
34
+ python - <<'PY'
35
+ import os, tomllib
36
+ from pathlib import Path
37
+ version = tomllib.loads(Path("pyproject.toml").read_text())["project"]["version"]
38
+ expected = "v" + version
39
+ actual = os.environ["RELEASE_TAG"].strip()
40
+ if actual != expected:
41
+ raise SystemExit(f"Tag {actual!r} does not match package version {expected!r}")
42
+ PY
43
+ - uses: actions/upload-artifact@v5
44
+ with:
45
+ name: orion-model-release-dist
46
+ path: dist/*
47
+ if-no-files-found: error
48
+ publish:
49
+ needs: build
50
+ if: ${{ inputs.confirm_publish == true }}
51
+ runs-on: ubuntu-latest
52
+ environment:
53
+ name: pypi
54
+ url: https://pypi.org/project/orion-verify/
55
+ permissions:
56
+ id-token: write
57
+ steps:
58
+ - uses: actions/download-artifact@v5
59
+ with:
60
+ name: orion-model-release-dist
61
+ path: dist
62
+ # Configure the PyPI Trusted Publisher for owner testfkij, repository orion-model,
63
+ # workflow .github/workflows/publish-pypi.yml, and environment pypi first.
64
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,12 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ .venv/
4
+ .env
5
+ *.db
6
+ .pytest_cache/
7
+ dist/
8
+ build/
9
+ *.egg-info/
10
+
11
+ # Local release/test logs and review artifacts
12
+ .build-review/
@@ -0,0 +1,15 @@
1
+ <!-- Docs reviewed: 2026-10-18; update this date and related docs with every code/security/API change. -->
2
+
3
+ # Official announcement: ORION Model
4
+
5
+ **ORION Verify is being rebranded as ORION Model.** The 0.5.0 alpha continues the same domain-ownership verification and browser anti-abuse project, with compatibility maintained for existing `orion-verify` Python installs, `orion_verify` imports, and command aliases during the transition.
6
+
7
+ This update adds `orion-model verify DOMAIN` for DNS ownership feedback, dedicated client/server connection modules, and the canonical `Codes.md` codebook. Security hardening adds a separate daily challenge request limit, a configurable proof-of-work threshold, single-attempt challenges, safer request-body handling, and scheduled retention cleanup.
8
+
9
+ ## Security status
10
+
11
+ ORION Model remains alpha software. This update is based on source review and automated local tests; it has **not** been independently audited and no public DDoS test was performed. Proof-of-work is not identity proof, and ORION Model must not replace your application's own authentication, authorization, CSRF protections, or account-creation checks. Run behind HTTPS, keep management endpoints private, separate the master key from each site's server secret, and configure edge rate limiting and monitoring.
12
+
13
+ ## Compatibility and release status
14
+
15
+ The existing PyPI distribution name `orion-verify` is kept in this codebase for compatibility. PyPI does not rename an existing project by changing source metadata; a new `orion-model` distribution would need its name checked and reserved on the target index, with publishing permissions configured. Version 0.5.0 is prepared in source here; do not treat it as published until the package index confirms upload.
@@ -0,0 +1,77 @@
1
+ <!-- Docs reviewed: 2026-10-18; update this date and related docs with every code/security/API change. -->
2
+
3
+ # HTTP API reference
4
+
5
+ All request bodies are JSON objects. The API applies request-size limits and conservative response headers. Production deployments should use HTTPS.
6
+
7
+ ## Health
8
+
9
+ GET /health
10
+
11
+ Returns service status and version. Do not use this endpoint alone as a readiness check for database-dependent operations.
12
+
13
+ ## Public challenge
14
+
15
+ POST /v1/challenges
16
+
17
+ Request body:
18
+
19
+ {"site_key":"or_pub_YOUR_SITE_KEY"}
20
+
21
+ The request Origin is checked against the active site's registered domain. A successful response includes challenge_id, nonce, and expires_in.
22
+
23
+ ## Submit proof
24
+
25
+ POST /v1/verify
26
+
27
+ Request body:
28
+
29
+ {"site_key":"or_pub_YOUR_SITE_KEY","challenge_id":"CHALLENGE_ID","proof":"12345"}
30
+
31
+ The proof must be the value found by the widget. Challenges expire, are bound to a site and source-IP digest, and can be consumed only once. Successful responses contain a short-lived token.
32
+
33
+ ## Server-side redemption
34
+
35
+ POST /v1/siteverify
36
+
37
+ Headers:
38
+
39
+ Authorization: Bearer YOUR_PRIVATE_SERVER_SECRET
40
+ Content-Type: application/json
41
+
42
+ Request body:
43
+
44
+ {"site_key":"or_pub_YOUR_SITE_KEY","token":"TOKEN_FROM_BROWSER"}
45
+
46
+ A valid token returns {"success":true} once. A second redemption returns false. Keep the secret only on the server. Do not use browser-origin requests for this endpoint.
47
+
48
+ ## Management endpoints
49
+
50
+ Management routes require both a valid X-ORION-Admin-Key and a client address inside ORION_ADMIN_ALLOWED_CIDRS.
51
+
52
+ - POST /v1/admin/sites — register a domain and create pending DNS ownership proof.
53
+ - POST /v1/admin/sites/verify — verify the DNS TXT proof and activate a site key.
54
+ - POST /v1/admin/sites/revoke — disable a key and invalidate outstanding challenges and tokens.
55
+
56
+ Management request bodies are deliberately limited to known fields. Keep these routes reachable only through a private management network.
57
+
58
+ ## Common response codes
59
+
60
+ | Status | Meaning |
61
+ |---|---|
62
+ | 200 | Request accepted; inspect the JSON body for success details. |
63
+ | 400 | Invalid body or verification request. |
64
+ | 401 | Missing/invalid management or server credentials. |
65
+ | 403 | Origin, ownership proof, or management network is not allowed. |
66
+ | 413 | Request body is too large. |
67
+ | 415 | JSON content type required. |
68
+ | 422 | Body fields or field lengths are invalid. |
69
+ | 429 | Quota or pending-challenge limit reached. |
70
+ | 503 | A required service, such as DNS, is unavailable. |
71
+
72
+ Error messages are intentionally generic for some failures. Do not expose secrets, tokens, or raw authorization headers in logs.
73
+
74
+
75
+ ### Challenge response additions (0.5.0)
76
+
77
+ `POST /v1/challenges` returns `challenge_id`, `nonce`, `expires_in`, and `difficulty_bits`. A client should honor the advertised difficulty for compatibility, but the server's configured `ORION_POW_DIFFICULTY_BITS` is authoritative. Valid or invalid proof submissions consume that challenge; request a new challenge after any failed proof. Challenge issuance is independently limited by `ORION_IP_DAILY_CHALLENGE_LIMIT` (default 120 per source IP per UTC day), while successfully issued tokens are separately limited by `ORION_IP_DAILY_TOKEN_LIMIT` (default 30).
@@ -0,0 +1,49 @@
1
+ <!-- Docs reviewed: 2026-10-18; update this date and related docs with every code/security/API change. -->
2
+
3
+ # ORION Model architecture
4
+
5
+ ORION Model is a self-hosted anti-abuse verification service. It is not an identity provider, CAPTCHA guarantee, account system, or replacement for application authorization.
6
+
7
+ ## Request flow
8
+
9
+ 1. An operator registers a site through the management API from a trusted network.
10
+ 2. The operator publishes the exact DNS TXT proof at _orion-verify.<domain>.
11
+ 3. The service resolves that record and activates the site key only when the proof matches.
12
+ 4. The public widget requests a short-lived challenge from the API.
13
+ 5. The browser solves the bounded proof-of-work challenge in a worker and submits the proof.
14
+ 6. The service issues a short-lived signed token after checking site state, origin, challenge expiry, single-use state, and quota.
15
+ 7. The application backend redeems the token with its private server secret. Redemption is single-use and site-bound.
16
+ 8. The application separately checks its own user session, CSRF token, permissions, rate limits, and business rules before performing a sensitive action.
17
+
18
+ ## Trust boundaries
19
+
20
+ - **Browser:** untrusted. The public site key is not a secret. Browser events and client-side UI state never authorize a protected operation by themselves.
21
+ - **Application backend:** owns user identity and authorization. It must never send the ORION server secret to the browser.
22
+ - **ORION API:** validates challenge proofs and token redemption. Protect the management API with the admin secret and management-network allowlist.
23
+ - **Database:** stores site records, challenge state, token redemption state, and hashed IP quota identifiers. Restrict network access and backups.
24
+ - **Reverse proxy:** trusted only when its direct peer is explicitly listed in ORION_TRUSTED_PROXY_CIDRS. Do not accept arbitrary client-supplied forwarding headers.
25
+
26
+ ## Persistence
27
+
28
+ SQLite is convenient for local development and tests. PostgreSQL is the recommended production database for multiple workers and concurrent requests. Configure backups, migrations, retention, monitoring, and restore tests before production use.
29
+
30
+ ## Operational controls
31
+
32
+ - Keep .env, database files, logs, backups, and secrets out of Git.
33
+ - Use HTTPS outside loopback development.
34
+ - Use a unique high-entropy master and admin secret.
35
+ - Keep management routes private; don't expose them to the public internet.
36
+ - Apply request-size and timeout limits at both the application and reverse proxy.
37
+ - Monitor 4xx/5xx rates, quota exhaustion, database availability, and DNS verification failures without logging tokens or secrets.
38
+ - Run the full test suite and dependency/security checks before each release.
39
+
40
+ ## Current scope
41
+
42
+ The repository includes the verification API, Python SDK, CLI, browser widget, a minimal integration demo, tests, and deployment examples. A multi-user hosted account portal is not currently part of the shipped API. Do not represent a static dashboard mockup as a working account system.
43
+
44
+
45
+ ## ORION Model 0.5.0 security changes
46
+
47
+ Challenges are single-attempt: the database conditional update and commit consumes a challenge before the proof is evaluated. An invalid proof cannot be repeatedly tested against the same nonce. Daily challenge request counts are recorded atomically in the existing daily quota table with an additive `challenge_requests` column; the existing `issued` count remains dedicated to token issuance. Retention cleanup is outside the hot request path and should be scheduled with `orion cleanup`.
48
+
49
+ The master signing key is held by the ORION Model service. Each registered site receives a separate one-time private server secret that is stored only by the associated application backend. Browser code receives only the public site key and one-time challenge token.
@@ -0,0 +1,38 @@
1
+ <!-- Docs reviewed: 2026-10-18; update this date and related docs with every code/security/API change. -->
2
+
3
+ # Changelog
4
+
5
+ ## Unreleased — ORION Model security and extension update (2026-10-18)
6
+
7
+ - Rebranded product docs to ORION Model while retaining the `orion-verify` distribution and `orion_verify` import namespace for compatibility.
8
+ - Added `orion --get GITHUB_FOLDER_URL` and `orion --uninstall NAME` with explicit confirmation, bounded file types/size, source/owner/version/storage logs, and no automatic code execution or dependency installation.
9
+ - Added a review-first anti-spam signal extension example and tests.
10
+ - Updated security notes for privacy-preserving anti-abuse signals, DDoS defense-in-depth, extension supply-chain risk, and audit scope.
11
+ - Fixed the demo test loader to avoid collision with Python’s standard-library `test` package and aligned the demo branding.
12
+ - The release is not independently audited and is not published to PyPI merely because local metadata changes.
13
+
14
+ ## 0.5.0 — 2026-10-18 — ORION Model alpha hardening
15
+
16
+ - Rebranded the product as ORION Model while retaining the `orion-verify` Python distribution/import name and old CLI aliases for compatibility.
17
+ - Added `orion-model verify DOMAIN` for DNS ownership activation/status feedback on the service host.
18
+ - Added `client_connect.widget_markup()` and `server_connect.connect_from_env()`; browser helpers accept only public site keys and server-side redemption uses a private per-site secret.
19
+ - Increased the default proof-of-work difficulty to 16 bits and made the allowed difficulty configurable from 12–20 bits; server-side checks remain authoritative.
20
+ - Added an independent atomic daily challenge-request quota (default 120 per IP), separate from the 30-token issuance quota.
21
+ - Changed verification challenges to be consumed before proof validation, preventing repeated guesses against the same live nonce.
22
+ - Moved expired-record cleanup out of public requests to `orion cleanup` maintenance to avoid unbounded work per challenge request.
23
+ - Added an additive database migration, canonical `Codes.md` codebook, and release/security documentation updates.
24
+ - Added tests for failed-proof challenge consumption, challenge quotas, connect-module input safety, and cleanup.
25
+
26
+ ## 0.4.0 — 2026-10-17
27
+
28
+ - Added `orion` / `orion-verify` CLI aliases and `quick-start`, `init`, `check`, and `cleanup` commands.
29
+ - Added DNS TXT ownership verification and key revocation; site keys remain inactive until verified.
30
+ - Added origin-aware CORS, request body limits, JSON content-type enforcement, safe response headers, and server-to-server bearer auth.
31
+ - Hardened SDK URL validation, TLS defaults, bounded timeouts, and redirect handling.
32
+ - Made daily quota increments atomic on PostgreSQL and SQLite; added concurrent quota test coverage.
33
+ - Added website integration codebook, security guidance, GitHub package-build workflow, and a gated manual PyPI workflow.
34
+ - Disabled legacy alpha registrations during schema upgrade until they are re-registered and domain-verified.
35
+
36
+ ## 0.3.0 — Alpha
37
+
38
+ - Initial self-hosted FastAPI/PostgreSQL verification service, widget, Python client, Docker Compose, and basic tests.
@@ -0,0 +1,40 @@
1
+ <!-- Docs reviewed: 2026-10-18; update this date and related docs with every code/security/API change. -->
2
+
3
+ # Contributing
4
+
5
+ Thanks for helping improve ORION Model. Security and correctness take priority over adding features.
6
+
7
+ ## Development setup
8
+
9
+ ```bash
10
+ python -m venv .venv
11
+ . .venv/bin/activate
12
+ python -m pip install -e '.[test]'
13
+ python -m compileall -q src tests
14
+ python -m pytest -q
15
+ ```
16
+
17
+ PostgreSQL-backed CI runs through GitHub Actions. When changing persistence, quota enforcement, token signing, DNS ownership, or origin rules, add tests for both success and rejection cases and consider concurrency and transaction rollback behavior.
18
+
19
+ ## Pull requests
20
+
21
+ - Keep changes focused and explain security consequences.
22
+ - Do not commit `.env`, secrets, verification tokens, real site keys, database dumps, or private customer data.
23
+ - Add/update README, `code.md`, `SECURITY.md`, and `CHANGELOG.md` when behavior changes.
24
+ - Keep the Python SDK fail-closed on network errors; do not turn outages into successful verification.
25
+ - Do not add invasive fingerprinting or claim proof-of-work proves humanity.
26
+ - Make sure test workflows and package builds pass before requesting review.
27
+
28
+ ## Reporting security issues
29
+
30
+ Follow the private reporting guidance in [`SECURITY.md`](SECURITY.md); do not publish exploit details before coordination.
31
+
32
+
33
+ ## Documentation is part of every change
34
+
35
+ Update `README.md`, `Codes.md`, `API_REFERENCE.md`, `ARCHITECTURE.md`, `SECURITY.md`, `SECURITY_AUDIT.md`, `THREAT_MODEL.md`, `CHANGELOG.md`, and `RELEASE_CHECKLIST.md` whenever a code change affects their behavior or public API. A version bump must update `pyproject.toml`, `src/orion_verify/__init__.py`, package metadata in the health endpoint, tests, and release documentation together. Never claim an independent audit or a published package without evidence from the external reviewer/index.
36
+
37
+
38
+ ## Documentation maintenance
39
+
40
+ When changing behavior, update README, Codes.md, API_REFERENCE.md, SECURITY.md, SECURITY_AUDIT.md, THREAT_MODEL.md, CHANGELOG.md, and ANNOUNCEMENT.md as applicable. Update the review date in each touched document. Never describe a local test run as an independent audit.