Changelog
⚠️ MANUAL REVIEW REQUIRED — Version numbers below reflect the Forge dev environment deploy counter at time of writing. Confirm the versioning scheme and align with the
package.json"version"field before the Marketplace listing goes live. App store versions visible to customers should follow semantic versioning (MAJOR.MINOR.PATCH).
v0.1.0 — 2026-05-21 (dev environment)
Free-tier monthly export ledger and HTTP 402 quota gate
- Export quota is now enforced before any signing or I/O — a quota-exceeded request costs no crypto resources
- Admin page shows live export count and exact UTC reset date
- HTTP 402 response on quota exceeded includes
limit,used,resetsAt, andcode: "monthly_export_limit_exceeded"— machine-readable for any integration - Admin page renders an upgrade banner with "resets in N days" when the quota is reached
v0.1.0 — 2026-05-20 (dev environment)
Issue panel and admin page UI
- Issue panel:
DynamicTablelayout (Time / Author / Activity / Status) withDD/MM HH:mm:sscompact timestamps - Issue panel: category lozenges per event type (COMMENT, STATUS, FIELD, etc.)
- Issue panel: trust footprint popup on each entry — entry ID, signature algorithm, TSA name, source event ID, copy-pastable
attestsys verify --entry-idCLI command - Issue panel: workspace-scope subtitle showing total verified entry count
- Issue panel: single-line footer with offline-verify CLI link and free-tier upgrade call-to-action
- Admin page: chain status band (
Audit Chain INTACT · verified [time] · Verify now · [Edition]) - Admin page: summary cards — Last entry, Retention, Timestamping, Verified entries, Exports this month
- Admin page: Recent activity list with clickable Jira deep-links
- Admin page: consolidated Subscription section with single Upgrade call-to-action
- Admin page: evidence bundle download (ZIP delivered as browser save)
- Forge AVI trigger fixes: correct event names, UUID-validated
cloudIdextraction, deduplication of overlapping Jira events
v0.1.0 — 2026-05-19 (dev environment)
Idempotent event ingestion and per-issue signed history
- Two-tier idempotency check: pre-transaction fast path + in-transaction race-safe re-check under
SELECT FOR UPDATE - Per-issue signed history:
GET /v1/forge/issues/{issueKey}/history?limit=N— returns newest-first, scoped to the issue, isolated by tenant - Cross-issue and cross-tenant isolation confirmed via integration tests
- Tenant auto-provisioning on first Forge app request — tenant row and active ECDSA signing key created together in one call
Foundation — 2026-05-12 (backend)
Phase 1B-Close: production-grade secret handling and GDPR erasure
- Real HMAC verification with AES-256-GCM envelope-encrypted keys — constant-time compare, key zeroized after use
FileBackedKmsClient: ECDSA private keys persisted with envelope encryption; signing unwraps short-lived buffer and zeroizes immediately after use- GDPR orphan-key erasure:
DELETE /v1/tenants/{cloudId}(operator-gated) appends a tombstone audit entry before wiping keys, preserving chain continuity - Erased tenants return HTTP 410 on any further ingestion attempt
Foundation — 2026-05-10 (backend)
Phase 1B: RFC 3161 multi-QTSP timestamp client and export bundle generator
FreeTsaClient(non-qualified, free tier) andQtspTsaClient(qualified, paid tiers)- Primary/secondary QTSP failover: QuoVadis Trustlink B.V. NL → GlobalSign nv-sa
TierRoutedTsaClient: FREE tier routes to FreeTSA; STANDARD / ADVANCED / ENTERPRISE route to QTSP — cross-tier isolation enforcedPendingTsaRetryService: background retry job for entries where the TSA was temporarily unreachable- Export bundle generator: signed ZIP with
manifest.json,entries/,public-keys/,tsa-certs/,cover.pdf,verify.html BundleRoundTripIT: 20-entry roundtrip integration test + mutation test (tampered entry correctly detected)
Phase 1A: hash-chain insert end-to-end
CanonicalJson(RFC 8785 JCS)HashChainCrypto:toSign,nextPrevHash,genesisPrevHash(32 zero bytes)- ECDSA secp256k1 with RFC 6979 deterministic signing (BouncyCastle)
- Per-tenant chain head lock:
SELECT FOR UPDATEontenant.tenant_chain_head— multi-pod safe POST /v1/eventsingestion endpointGET /v1/events/{cloudId}/verify— accumulates all failures, no short-circuitChainConcurrencyIT: 100-entry concurrent chain + full ECDSA verification (Testcontainers + TimescaleDB)