All notable changes to Trust Layer are documented here. Format follows Keep a Changelog. Versions follow Semantic Versioning.
- unpack submit_hash tuple in recovery + poll proof status before TSR check
- HEAD 404 body mismatch + smoke test retry for TSA fallback
- replace get_event_loop() with async def in test_stripe_no_key
- upgrade starlette 1.0.0→1.1.0 and idna 3.15→3.16
- add #trust hash to Trust Layer pricing URLs
- add POST /create-checkout-session endpoint
- deactivate orphan trial keys on paid upgrade + track trial_to_paid conversions
- make pip-audit blocking — skip editable packages instead of continue-on-error
- patch STRIPE_LIVE_KEY in bot-UA checkout test
- strengthen bot-UA checkout test assertions (== live key, not != test key)
- add bot-UA live-mode test coverage for /v1/keys/trial endpoint
- stop bot-UA guard from silently blocking real customers in checkout
- route Scanner Pro to separate Stripe product/price
- trial endpoint respects product=scanner + admin alert on pricing misconfigured
(no user-facing changes)
- add GET /trial landing page for badge and CLI CTAs
- break circular upgrade_url fallback pro-signup→pricing
- expires_at 14d→23h + Stripe session for existing trials
- add Free Tier badge + signup CTA
- add is_external safety net to prevent LIVE customer creation from non-external visitors
- card-free 14-day trial via POST /v1/keys/trial
- upgrade urllib3 (CVE-2026-44431, CVE-2026-44432), pytest (CVE-2025-71176), and refresh dependency versions
- add OVH IPv6 to _INTERNAL_IPS, 'verify'/'flow-' to test-email guards, burst rate-limit 3/10min
(no user-facing changes)
- add diagnostic event_type+sig_prefix to signature failure logs
- harden internal IP mode guard + _is_test_email coverage
(no user-facing changes)
- force test mode for diagnostic/internal emails
- use body referrer for visitor classification in /v1/keys/setup
- add is_external visitor attribution to checkout funnel events
- email delivery monitoring + per-email rate limiting
(no user-facing changes)
- include y as vowel in gibberish detection to reduce false positives
- anti-spam email validation + 24h expiry + Link payments
- public /v1/demo endpoint for prospect conversion
- non-repudiation positioning — tagline + CTA banner
- force test mode for RFC 2606 reserved email domains at source
- add scanner_pro_subscription routing regression test
- handle scanner_pro_subscription in checkout webhook handler
- fix dns.resolver import scope in _verify_mx
- add DNS MX validation to reject fake email domains
- add DNS MX validation to reject fake email domains
(no user-facing changes)
- update test email domain to non-blocked domain after disposable email blocklist
- route Scanner Pro through Checkout Sessions with real 14-day trial + block disposable emails
- add honeypot anti-bot check to signup endpoints
- add MCP_SCAN_PINGS_LOG to config exports
- add rate limiting to /v1/keys/setup endpoint
- add CTEF constraint_evaluation mapping + tier_upgrade_proof v0.3.2 notes
- upgrade dependencies — cryptography 46→47, fastapi 0.135→0.136, stripe 15.0→15.1, uvicorn 0.42→0.46
- CTEF cross-implementation reference in user-guide: constraint_evaluation field mapping (AgentGraph→ArkForge),
no_critical_findingsenforcement gate,tier_upgrade_proofcomposable envelope example - document v0.3.2 alignment: depth-first proof-stripping, canonical-bytes-diff fixture, 3 constraint_evaluation test vectors (within-limit/near-miss/exceeded)
- add UTM tracking to README and email template links
- add upgrade_url to free-signup API response
- add UTM tracking to Stripe checkout cancel, portal return, and abandoned checkout email URLs
- checkout abandonment recovery + email resolution fallback
- record web signups in MCP registration_log for register_free_key_calls_web
- add Pro upgrade CTA to free welcome email
- filter internal/test scans from cta_impression metrics
(no user-facing changes)
- add POST /api/register endpoint for MCP phone-home registration
- log tool_names and plan in scan_events.jsonl
(no user-facing changes)
- dynamic FAILOVER_MODE via state file — eliminates stale systemd env var
- add User-Agent to all raw urllib requests
- add User-Agent header to prevent 403 from empty UA filter
- always return dict from req() to prevent AttributeError
- always expose mode/write_enabled, harden smoke test
- always expose mode and write_enabled fields
- add server-side scan counter to /v1/stats + scan_events.jsonl
- add POST /v1/contact enterprise demo request endpoint
- use noreply@arkforge.tech as SMTP from address — arkforge.fr not verified on Resend
- add Rekor independent verify URL to proof email
- Phase 3b — capturer stderr twine, revert on failure, idempotent on already-exists
- sync arkforge-mcp à chaque livraison TL (Phase 3b)
- pricing URL arkforge.fr → arkforge.tech
- add _links.pricing CTA in JSON responses for scan-to-pricing conversion
(no user-facing changes)
- NIST AI RMF 1.0 + SOC 2 Readiness frameworks — v1.3.23
- NIST AI RMF 1.0 compliance framework —
POST /v1/compliance-reportaccepts"framework": "nist_ai_rmf". Maps Trust Layer proof fields to 7 subcategories across GOVERN, MAP, MEASURE, MANAGE:- GOVERN 1.1 Risk Policies (not_applicable), MAP 1.1 Context (spec + agent_identity), MAP 5.2 Risk Tracking (chain hash), MEASURE 1.1 Measurement (integrity), MEASURE 2.5 Monitoring (RFC 3161), MANAGE 1.3 Treatment (chain + integrity), MANAGE 4.1 Monitoring (proof_id + timestamp)
- SOC 2 Readiness framework —
POST /v1/compliance-reportaccepts"framework": "soc2_readiness". Maps to 6 AICPA Trust Service Criteria:- CC6.1 Logical Access (buyer_fp + seller), CC6.7 Transmission Integrity (all 3 hashes), CC7.2 Security Monitoring (RFC 3161), PI1.1 Completeness (integrity), PI1.2 Accuracy (proof_id + timestamp + fee), A1.1 Availability (not_applicable)
- Prominent disclaimer: readiness evidence only, not a formal SOC 2 audit opinion
- 27 new tests — map_proof + generate_report + endpoint integration for both frameworks. 522 → 549 total, 0 regressions.
README.md— compliance reports section listing all 4 frameworks with curl example.docs/user-guide.md— NIST AI RMF and SOC 2 Readiness sections with criteria tables.docs/quick-reference.md— compliance endpoint updated to list all 4 frameworks.
POST /v1/compliance-reportdocstring: lists all 4 supported frameworks.docs/user-guide.md: "More frameworks planned" note replaced with full list.
- ISO/IEC 42001:2023 compliance framework —
POST /v1/compliance-reportnow accepts"framework": "iso_42001". Maps Trust Layer proof fields to 6 AI Management System clauses:- § 6.1 Risk and Opportunity Management —
hashes.chainpresence - § 8.2 AI Risk Assessment — proof integrity verifiability
- § 8.4 AI System Lifecycle Documentation —
spec_version+parties.agent_version - § 9.1 Monitoring, Measurement and Evaluation — RFC 3161 verified timestamp
- § 9.2 Internal Audit — cryptographic audit trail integrity
- § 10.1 Nonconformity and Corrective Action —
not_applicable(organisational obligation)
- § 6.1 Risk and Opportunity Management —
- 19 new tests —
ISO42001Framework.map_proof,generate_report, endpoint integration. 504 → 523 total, 0 regressions. docs/user-guide.md— full ISO 42001 section with curl + Python examples, clause coverage table.docs/quick-reference.md— compliance endpoint updated to list both frameworks.
POST /v1/compliance-reportdocstring updated: listseu_ai_act, iso_42001as supported frameworks.- Error message for
unknown_frameworknow dynamically lists all registered frameworks (includingiso_42001).
- update_changelog.py reçoit HEAD + label séparé — le tag n'existe pas encore au moment de l'appel
- fix proof index version reference (v1.4.0 → v1.3.18) + minor README/deps updates
- Proof index: DualWrite resilience —
DualWriteProofIndexreplaces pureRedisProofIndexwhen Redis is available. JSONL is now always written first (durable source of truth); Redis is written second (fastZRANGEBYSCOREqueries). If Redis fails mid-write, the JSONL entry is already committed — no data loss.
- Automatic JSONL→Redis reconciliation — two background daemon threads handle sync without operator intervention:
- Startup reconciliation: full JSONL replay into Redis on every service (re)start. Recovers from Redis data loss after restart.
- Periodic reconciliation: re-replays the last 25 hours of JSONL into Redis every 5 minutes. Recovers from Redis outages that occur while the service is running, without requiring a service restart.
DualWriteProofIndex.reconcile(since_unix=None)— callable method for manual or scripted reconciliation.backfill_proof_index.py --from-jsonlmode — replays JSONL directly into Redis (faster than scanning proof files). Supports--since ISO8601for incremental reconciliation.- Ops documentation in
docs/user-guide.md— resilience model, reconciliation triggers, manual commands.
POST /v1/assess— MCP server security posture assessment. Analyzes a server manifest for dangerous capability patterns (PermissionAnalyzer: filesystem write, code execution, env access, network), tool drift (DescriptionDriftAnalyzer: additions/removals/description changes viadifflib), and version regressions (VersionTrackingAnalyzer). Returnsrisk_score(0–100), categorized findings, and baseline diff. Baseline stored per(api_key, server_id)indata/mcp_baselines/. Rate limit: 100 calls/day per API key.POST /v1/compliance-report— EU AI Act compliance report. Aggregates certified proofs for an API key over a date range and maps them to 6 articles: Art. 9 (risk management), Art. 10 (data governance — not applicable), Art. 13 (transparency), Art. 14 (human oversight), Art. 17 (quality management), Art. 22 (record-keeping). Returns per-article coverage status (covered/partial/gap/not_applicable) with evidence summaries and a gaps list.ProofIndexBackendABC — pluggable proof index abstraction.RedisProofIndex(ZADD/ZRANGEBYSCORE, 90-day TTL) +FileProofIndex(JSONL append,threading.Lock) fallback. Powers date-range queries for compliance reports without scanning all proof files.scripts/backfill_proof_index.py— one-shot migration to index proofs created before v1.3.18.- APIRouter pattern — first use of
fastapi.APIRouterin the codebase. New routes are isolated modules undertrust_layer/routers/. Existingapp.pyroutes are untouched.
- ROADMAP updated to reflect implemented features: agent identity, DID binding, Platform plan, proof privacy model (
/v1/proof/{id}/full),/v1/proof/{id}/verifyendpoint.
- Platform plan TSA routing unit tests: Platform keys skip FreeTSA, fall back to Sectigo; non-platform plans retain FreeTSA-first behaviour.
- E2E integration tests for Platform plan: key prefix detection, plan propagation to
submit_hash, DigiCert TSA confirmed on live proof.
- Platform plan — 599 EUR/month, 500,000 proofs/month, for platforms and AI integrators. API key prefix
mcp_plat_. Overage opt-in at 0.002 EUR/proof. - DigiCert-first TSA routing for Platform keys — Platform API keys skip FreeTSA and use DigiCert as primary timestamp authority. FreeTSA is a community service with no SLA; DigiCert is WebTrust-certified with enterprise-grade reliability. Fallback chain: DigiCert → Sectigo (unchanged). All other plans retain FreeTSA-first behaviour.
- Platform plan exposed in
GET /v1/pricing. - Stripe product + price IDs (live and test) added to vault and loaded via
config.py.
- Upgrade stripe 14.4.1 → 15.0.0. Adapted to
StripeObjectno longer inheriting fromdict: webhook handler uses dot notation (event.id,event.type,event.livemode,event.data.object.to_dict()); payment provider usescustomer.invoice_settingsdot notation. Updated test mocks accordingly.
parties.did_resolution_statusfield in proof receipts."bound"whenagent_identityis a cryptographically verified DID bound via Ed25519 challenge-response or OATR delegation at registration time."unverified"whenagent_identityis caller-declared without cryptographic verification. Absent if noagent_identityis provided.
GET /v1/proof/{id}now includesagent_identityandsellerin public responses.buyer_fingerprintremains authenticated-only. Third-party auditors and WG members can verify agent identity without API key access.
GET /v1/proof/{id}no longer exposesprovider_paymentdetails (receipt URL, parsed fields),parties,certification_fee,buyer_reputation_score, orbuyer_profile_urlin public responses. Onlyreceipt_content_hashandverification_statusremain visible inprovider_payment.
GET /v1/proof/{id}/full— authenticated endpoint (API key required, owner only). Returns the complete proof including payment details, parties, and certification fee. Ownership verified viasha256(api_key) == parties.buyer_fingerprint.
- Payment amounts, Stripe receipt URLs, parsed payment fields, buyer/seller identities, and reputation scores are no longer publicly visible on
GET /v1/proof/{id}.
- CI pipeline: validate release workflow produces green run after v1.2.1/v1.2.2 CHANGELOG commit fix.
- CI release: CHANGELOG commit moved to deploy script (pre-tag) — avoids branch protection conflict during CI.
- CI fallback PR path for CHANGELOG commit when API commit is blocked.
- Dependency update: cryptography 43.0.0 → 46.0.5 — patches 3 Dependabot CVEs (cee19b8)
- Conformance: branch chain_hash by
algorithmfield (legacy vs canonical_json) (b28ee18)
- Chain hash algorithm changed for spec_version 1.2 / proof-spec 2.1.
The chain hash is now computed over a canonical JSON dict (sorted keys) instead of a raw string concatenation. This eliminates preimage ambiguity when field values contain separator characters.
Proofs issued before v1.2.0 (spec_version 1.1) continue to verify correctly via the legacy path in
verify_proof_integrity().
- CRITICAL — chain hash preimage ambiguity (CVE-equivalent).
String concatenation
request_hash + response_hash + payment_intent_id + ...allowed crafted values to produce collisions. Fixed by switching tosha256(canonical_json({...}))for spec_version ≥ 1.2.
proof-spec v2.1.0alignment:verify_proof_integrity()routes byspec_versionfield (1.1/2.0 → legacy, 1.2/2.1 → canonical_json).- Conformance test suite
tests/test_spec_conformance.py: branches chain hash computation byalgorithmfield in test vectors. 27/27 vectors pass.
- Proof abuse auto-block:
proof_abuse:{ip}checked in Redis at the top ofget_proof(), returns HTTP 429 immediately (previously only logged). - Dependency pinning:
requirements.txtnow uses==exact versions (pip freeze);requirements-dev.txtseparated. Gardien Check 2 covers CVEs viapip-audit. - SAST:
nosec B104annotations on intentional host bindings (0.0.0.0).
- Templates: footer link
arkforge.fr→arkforge.tech(domain migration).
- All internal URLs and redirect targets migrated
arkforge.fr/trust→arkforge.tech/trust(Stripe success/cancel/return URLs, nginx redirects).
- Domain migration
arkforge.fr→arkforge.techfor all public-facing URLs.
- Welcome email: replaced generic text with actionable first-proof example for free tier users.
- CI gate: fallback to recent runs if no run directly on
main(handles post squash-merge PRs).
- README rewrite: removed internal TSA provider names; public-facing language only.
- Mode C (
extra_headers) usage guide, Redis env var reference, systemd--workers 4example.
- Redis hot path rate limiting (atomic
INCR + EXPIRE): correct shared state across multiple uvicorn workers. In-memory fallback if Redis unavailable. - Multi-worker readiness: shared rate limit state via Redis.
- Removed daily cap for all plans (Free/Pro/Enterprise). Monthly quota only — no per-day rate restriction.
- Dynamic daily cap per plan: Free=100, Pro=500, Enterprise=5,000 proofs/day.
extra_headers: forwarding credentials to target APIs documentation.- Proxy limits: full section (timeout, payload size, methods, format, daily cap).
extra_headershardening: strict header allowlist, hop-by-hop filtering, dogfooding via certified GitHub comments.
(internal version bump — no user-facing changes)
- Removed pay-per-use pricing model (€0.10/proof): billing now subscription-only.
- Free tier test keys updated; test suite aligned.
- SSRF expansion: CGNAT ranges, IPv4-mapped IPv6, 6to4 added to
_PRIVATE_NETWORKSblocklist.
- Security: uvicorn
127.0.0.1binding rationale,pip-auditintegration, network exposure model.
- Transactional email migrated from OVH SMTP to Resend (better deliverability, API-based).
- Smoke tests: use
@smoke.invalidemail addresses to prevent real SMTP delivery during test runs.
- API keys encrypted at rest with Fernet (AES-128).
KEYS_FERNET_KEY_FILEenv var controls key path. 7-year retention.
- Staged blue/green rollout via HA infra (failover-first strategy).
- Smoke test suite: 5 post-deploy validation sections.
- Versioning unified:
__init__.pyauto-bumped by deploy script. - Rollback:
git reset --hard+ post-rollback verification.
- User guide: subscription lifecycle, billing portal, email alerts.
(initial 1.1.x series — internal stabilisation)
- Stripe webhooks:
invoice.paidandinvoice.payment_failedhandlers.