Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
bddc90b
test(preflight): complete Phase 0 audit, MSW isolation, and 100% gate…
nani224 Sep 19, 2026
c02cc16
contract: v0.3 continuous operation schema
Sep 19, 2026
26c5be8
feat: v0.3 continuous operation (scheduler, drift, probes, alerts, hs…
Sep 19, 2026
0510bdd
feat(estate): implement Screen 11 continuous estate console with full…
nani224 Sep 20, 2026
0e3e583
feat(trend): implement Screen 12 estate cryptographic trend with full…
nani224 Sep 20, 2026
8d301b6
feat(drift): implement Screen 13 cryptographic drift analysis with fu…
nani224 Sep 20, 2026
4d264ac
feat(alerts): implement Screen 14 security alerts and probe surface w…
nani224 Sep 20, 2026
70dbebd
merge: feature/a1-backend into main (v0.3 continuous operation: sched…
claude Sep 20, 2026
5b02b18
merge: Track CC detection engine + corpus + CI/CD (M0-M9)
claude Sep 20, 2026
72f6650
merge: feature/a2-frontend into main (v0.3 screens 11-14: estate, tre…
claude Sep 20, 2026
88afa13
fix(api): include line number in drift finding identity (Track A1 P4)
claude Sep 20, 2026
02135b9
merge: A1 drift finding-identity fix into main
claude Sep 20, 2026
59dee55
fix(probes): support DER peer cert extraction in CERT_NONE mode and s…
nani224 Sep 20, 2026
79d2345
fix(api): /estate/trend avgRiskScore blew past 100 on multi-scan days
claude Sep 20, 2026
03b8144
feat(compose): extend docker-compose.yml with weak-TLS/registry demo …
claude Sep 20, 2026
b316f0f
docs(security): review + annotate bandit B608/B202 findings (Track A1…
claude Sep 20, 2026
b136314
fix(security): air-gap verification never covered probes/ or schedule…
claude Sep 20, 2026
9b5e9f8
fix(a11y): make /specimen scroll container keyboard-focusable
claude Sep 20, 2026
ecbaaf8
fix(security): patch postcss HIGH CVEs via pnpm override; document cr…
claude Sep 20, 2026
94172aa
fix(perf): SQL-level pagination for GET /findings (700ms -> 8ms p50 a…
claude Sep 20, 2026
ab41dbe
docs(release): rewrite README, add DEMO_SCRIPT + CHANGELOG for v0.3.0…
claude Sep 20, 2026
73e0513
docs(bookkeeping): update PLAN.md and PROGRESS.md with the finale pas…
claude Sep 20, 2026
07215b6
release: v0.3.0-sih-finale — final integration, verification & releas…
nani224 Sep 20, 2026
fbec086
docs(release): document v0.3.0-sih-finale tag push being blocked
claude Sep 20, 2026
2208d0c
docs: document v0.3.0-sih-finale tag push blocker (ADR 023) (#15)
nani224 Sep 20, 2026
8f41441
merge: A1 Windows SoftHSM/DER-cert probe fix into main
claude Sep 20, 2026
f341e8f
merge: A1 Windows SoftHSM/DER-cert probe fix missed by the finale mer…
nani224 Sep 20, 2026
d96e06b
docs(release): update ADR 023 for the A1 Windows fix merge (PR #16)
claude Sep 20, 2026
ecc4078
docs: update ADR 023 for the A1 Windows fix merge (PR #16) (#17)
nani224 Sep 20, 2026
f4f78e4
chore(repo): remove root screenshots (duplicate frontend/public/scree…
claude Sep 20, 2026
ffb29f4
chore(repo): relocate agent-scaffolding files to docs/engineering/
claude Sep 20, 2026
66662ef
fix(docs): repoint 001-phase0-skeleton.md's TOOLBELT.md reference (mi…
claude Sep 20, 2026
5744beb
chore(repo): audit frontend/public/screenshots -- keep one canonical set
claude Sep 20, 2026
31944f9
feat(engine): M1 span provenance for all findings across languages
nani224 Sep 20, 2026
77b1825
feat(engine): M2 rule-independent extractors (tables, entropy, arx, b…
nani224 Sep 20, 2026
34799f1
feat(engine): M3 attribution calculus, falsifiable exclusions, and co…
nani224 Sep 20, 2026
da5fbde
feat(engine): M4 Coverage Certificate and CycloneDX 1.6 embedding
nani224 Sep 20, 2026
11e8191
feat(engine): M5 The Four Kill Tests (K1 sensitivity, K2 specificity,…
nani224 Sep 20, 2026
a60801e
feat(engine): M6 debt-closure loop CLI and end-to-end residue cluster…
nani224 Sep 20, 2026
922e5b7
feat(engine): M7 — PS-mandated detection gaps, binary/firmware parity…
nani224 Sep 20, 2026
e71a212
feat(bench): M8 — Public benchmark suite, score.py, PROTOCOL.md, RESU…
nani224 Sep 20, 2026
09ebb51
fix(engine): resolve mypy strict typing and bench evaluate regression…
nani224 Sep 20, 2026
99b22a2
docs: complete M7, M8, and Section 6 reports with genuine verificatio…
nani224 Sep 20, 2026
10a85ce
chore(repo): gitignore frontend/public/screenshots/ (missed in prior …
claude Sep 21, 2026
04c12ed
docs(demo): document how to restore and reproduce the vulnerable-app …
claude Sep 21, 2026
6f1f8ee
docs(decisions): renumber backend ADRs by topic, not build phase
claude Sep 21, 2026
c85c45a
fix(docs): repoint every ADR reference to the new topical numbering
claude Sep 21, 2026
cc6137f
docs: add operator documentation (INSTALL, OPERATIONS, API, ARCHITECT…
claude Sep 21, 2026
2b32e26
docs(readme): link into docs/, fix a loose ADR-directory reference, f…
claude Sep 21, 2026
bd58065
fix(docs): repoint Makefile's stale ADR reference (missed by the scri…
claude Sep 21, 2026
3b9ecad
chore: repository hygiene & reorganisation (#18)
nani224 Sep 21, 2026
91c7af3
feat(contract): M1 — Contract v1.0.0, coverage/debt/criticality/cloud…
nani224 Sep 20, 2026
1ac27c9
feat(api): M2 — Coverage persistence, content-hash indexing, and p95 …
nani224 Sep 20, 2026
9d4515f
feat(api): M3 — Debt ledger state machine, audit chain logging, and r…
nani224 Sep 20, 2026
5ba2d8b
fix(tests): update audit-log assertion for M2's coverage.record entry
claude Sep 21, 2026
2840677
feat(api): M4 — coverage in drift and trend, plus a real cert-keying …
claude Sep 21, 2026
a00c1d6
docs(progress): record M1-M4 evidence (rebase, verification, real cur…
claude Sep 21, 2026
aa24111
feat(api): M5 - criticality feeds risk K/E, facing reported estate-wide
claude Sep 21, 2026
0cfd901
docs(progress): record M5 evidence (criticality reranking, facing spl…
nani224 Sep 21, 2026
5419cc3
feat(probes): M6 - cloud key discovery, public key fingerprinting, ai…
nani224 Sep 21, 2026
9d47935
feat(api): M7 - performance load test suite, security audits, and v1.…
nani224 Sep 21, 2026
dacd1d0
feat(ui): complete Track A2 - Coverage Certificate, Residue Explorer,…
nani224 Sep 21, 2026
fe1f185
fix(contract): remove duplicate DriftSnapshot coverageRatio and resid…
nani224 Sep 21, 2026
ffdfb0c
merge: Track A1 (feature/cmc-api) into release/v1.0.0
nani224 Sep 21, 2026
dc8e5b7
merge: Track CC/Engine (feature/cmc-engine) into release/v1.0.0
nani224 Sep 21, 2026
4402e81
chore(repo): remove root PROGRESS.md merged from engine track for rep…
nani224 Sep 21, 2026
268978f
merge: Track A2 (feature/cmc-ui) into release/v1.0.0
nani224 Sep 21, 2026
e95cf17
fix(security): annotate validated float interpolation in CTE query wi…
nani224 Sep 21, 2026
5fb1c22
docs(release): finalize documentation, demo script, QA pack, and chan…
nani224 Sep 21, 2026
6234490
merge: release/v1.0.0 into main (v1.0 CMC work)
nani224 Sep 21, 2026
0a140d2
fix: rescore SQL comment-in-string bug breaking bulk rescore; fix bro…
nani224 Sep 21, 2026
e495c2c
docs: add ADR 024 for crypto mass conservation architecture
nani224 Sep 21, 2026
f1000a7
docs: update README with verified v1.0 test counts and source file me…
nani224 Sep 21, 2026
be3ebf7
contract: v1.0.1 add bearer auth
nani224 Sep 21, 2026
705086a
feat(api): implement shared bearer auth dependency and production tok…
nani224 Sep 21, 2026
dfe7df0
feat(api): replace wildcard CORS with explicit env-configurable origins
nani224 Sep 21, 2026
7fc0a2c
feat(api): require X-ECDAT-Actor header on writes and record on audit…
nani224 Sep 21, 2026
6c1ed22
feat(api): add request size limit middleware capping JSON bodies at 1MB
nani224 Sep 21, 2026
f97c012
feat(probes): redact webhook URLs and credentials in logs and audit r…
nani224 Sep 21, 2026
3b35449
test(engine): prove CMC K2 specificity against real benign codebase
nani224 Sep 21, 2026
ce2fa51
feat(api): structured logging with actor and entity context across ro…
nani224 Sep 21, 2026
6b4bf5e
feat(api): healthcheck verifies database connectivity and engine version
nani224 Sep 21, 2026
526f77c
test(engine): verify scan recovery on mid-run interruption
nani224 Sep 21, 2026
a700e1b
docs(ops): documented and tested backup/restore procedures
nani224 Sep 21, 2026
41c48fb
feat(frontend): send auth token and actor headers, handle 401 as desi…
nani224 Sep 21, 2026
d58b9a7
fix(api): clean websocket router separation, exception payload format…
nani224 Sep 21, 2026
f93e8d4
docs: update README numbers and rate-limit documentation for producti…
nani224 Sep 21, 2026
345abb9
merge: fix/frontend-auth into fix/production-hardening (integrate fro…
nani224 Sep 27, 2026
4222a8c
fix(frontend): harmonize auth integration, WCAG a11y contrast, CLS la…
nani224 Sep 27, 2026
eb0ca5a
ci(deploy): add Vercel and Render configurations for 24/7 cloud hosting
nani224 Sep 28, 2026
5f33851
docs: add 24/7 free cloud deployment guide for Vercel and Render
nani224 Sep 28, 2026
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
10 changes: 5 additions & 5 deletions .claude/agents/backend-auditor.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ description: Re-verifies backend/ from scratch (ruff, mypy, pytest, hypothesis,
tools: Read, Grep, Glob, Bash
---

You audit `backend/` for the ECDAT project. Read `/home/user/SIH26164/CLAUDE.md` and
`backend/CLAUDE.md`/`PLAN.md`/`PROGRESS.md` first, but treat everything they claim as
UNVERIFIED until you personally re-run the command that proves it. Do not trust commit
messages, README badges, or PROGRESS.md lines.
You audit `backend/` for the ECDAT project. Read `/home/user/SIH26164/CLAUDE.md`,
`backend/CLAUDE.md`, and `docs/engineering/backend/PLAN.md`/`PROGRESS.md` first, but treat
everything they claim as UNVERIFIED until you personally re-run the command that proves it.
Do not trust commit messages, README badges, or PROGRESS.md lines.

Run, in `backend/`, with `uv`:
- `uv run ruff check .`
Expand All @@ -34,7 +34,7 @@ Run, in `backend/`, with `uv`:
available.

For EVERY phase claimed complete in commit history (Phase 1 through Phase 10 per
`backend/PLAN.md`/git log), check that the code backing that phase's claim actually exists
`docs/engineering/backend/PLAN.md`/git log), check that the code backing that phase's claim actually exists
and does what the commit message says — not just that a file with a plausible name exists.
Spot-check the actual logic, not just presence.

Expand Down
11 changes: 6 additions & 5 deletions .claude/agents/frontend-auditor.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ description: Re-verifies frontend/ from scratch (typecheck, lint, knip, vitest,
tools: Read, Grep, Glob, Bash
---

You audit `frontend/` for the ECDAT project. Read `/home/user/SIH26164/CLAUDE.md` and any
`frontend/CLAUDE.md`/`PLAN.md`/`PROGRESS.md`/`LEARNINGS.md` first, but treat every claim in
them (and any prior "COMPLETE" audit report) as UNVERIFIED until you personally re-run the
command that proves it. Spot-check at least 3 specific claims from the frontend's own prior
audit reports against real output rather than re-trusting the report wholesale.
You audit `frontend/` for the ECDAT project. Read `/home/user/SIH26164/CLAUDE.md` and
`docs/engineering/frontend/PLAN.md`/`PROGRESS.md`/`LEARNINGS.md` first (frontend has no
CLAUDE.md of its own), but treat every claim in them (and any prior "COMPLETE" audit report)
as UNVERIFIED until you personally re-run the command that proves it. Spot-check at least 3
specific claims from the frontend's own prior audit reports against real output rather than
re-trusting the report wholesale.

In `frontend/`, using the repo's package manager (check for `pnpm-lock.yaml` — use `pnpm`):
- `pnpm typecheck` (or `tsc --noEmit` if no such script)
Expand Down
2 changes: 1 addition & 1 deletion .claude/commands/bench.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ description: Run all backend benchmark/evaluation scripts and report real precis
In `backend/`, find and run every script under `bench/` that computes precision/recall/F1
or runs hostile-input tests (e.g. `bench/evaluate.py`, `bench/real_world/evaluate.py`, any
`realworld_sample.py`, any `hostile_tests.py`). Print the real numbers for each. Then grep
`README.md` and `backend/PROGRESS.md` for any quoted precision/recall/F1 claim and state,
`README.md` and `docs/engineering/backend/PROGRESS.md` for any quoted precision/recall/F1 claim and state,
for each, whether the real number just measured matches, and if not, by how much and what
you did about the discrepancy (fixed the claim, or flagged it as a real regression).
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,14 @@ build/
uv.lock.bak
*.db
*.db-journal
*.db-shm
*.db-wal
backend/bench/demo_corpus/

# e2e specs write here on every Playwright run (page.screenshot() +
# fs.existsSync assertions, not pixel-diff visual baselines -- no
# toHaveScreenshot() usage in this repo). The canonical, documentation-
# worthy captures live in docs/screenshots/ instead; this directory is
# regenerated output, not a fixture.
frontend/public/screenshots/

182 changes: 182 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# Changelog

## v1.0.0 — Crypto Mass Conservation (CMC) & PS Gap Closure — 2026-09-21

The "Crypto Mass Conservation" release. ECDAT pairs detection with mass conservation:
measuring not just what was found, but mathematically accounting for what was unexplained
(crypto debt residue). Closes key problem-statement (PS) gaps including business criticality
reranking, cloud KMS key discovery (LocalStack), and cryptographic estate coverage.

### Track A1 — Coverage API, Debt Ledger, PS-Gap Closure

- **M1: Contract v1.0.0**: Added OpenAPI schemas for `CoverageCertificate`, `ArtifactCoverage`,
`ResidueCluster`, `AssetCriticality`, `CloudKeyRecord`, and `EstateCoverage`.
- **M2: Coverage Persistence**: Persisted coverage certificates and per-artifact coverage
with content-hash deduplication (`save_coverage`/`get_coverage_certificate`), ensuring
reproducible coverage numbers and identical cluster IDs across scans. Latency budget
met: p95 < 150ms.
- **M3: Debt Ledger State Machine**: Residue cluster lifecycle (`open` -> `promoted` | `excluded` | `accepted`)
with tamper-evident SHA-256 audit chaining. Strict validation: exclusions require justification
and owner; promoted clusters are terminal. Real-time alert rule `check_residue_rise`.
- **M4: Coverage in Drift & Trend**: Wired `coverageRatio` and `residueMass` through scan snapshots
and calculate_drift(), tracking `coverageDelta` and `residueMassDelta`.
- **M5: Business Criticality Reranking**: Operator-managed `AssetCriticality` records translated
into synthetic higher-priority `ContextWithGlob` policy entries, visibly adjusting K/E exposure
and Mosca risk scores on subsequent scans without altering engine formula. Derivation of
`internalFacingAssets`/`externalFacingAssets` in `EstateSummary`.
- **M6: Cloud Key Discovery**: Self-hosted AWS KMS probe via LocalStack (`backend/probes/cloud_kms.py`)
with public key fingerprinting (`identityId`), finding join, allowlisted destination guard, and
clean degradation. Azure Key Vault and GCP Cloud HSM documented under `[Roadmap]`.
- **M7: Hardening & Performance**:
- Benchmark on 10k findings + coverage: p95 for coverage queries < 46ms (budget: 150ms);
p95 for residue queries < 7ms (budget: 200ms).
- Security scans: `bandit` (0 issues identified), `pip-audit` (1 package exception in ADR 017).

### Track CC/Engine — Residue Extractors, Attribution Calculus, Kill Tests & Benchmark

- **M1-M2: Rule-Independent Extractors**: Implemented 6 extractor classes (`tables`, `arx`, `entropy`,
`bigint`, `framing`, `literals`) with zero imports from detection rules, detecting unmodelled crypto.
- **M3: Attribution Calculus & Conservation Invariant**: Mathematically verified
$M_{\text{attributed}} + M_{\text{excluded}} + M_{\text{residue}} = M_{\text{total}}$ on all 33 corpus artifacts with zero units lost.
- **M4: Coverage Certificate & CBOM Embedding**: CycloneDX 1.6 CBOM export with embedded coverage certificate
and SHA-256 run manifest, validated against strict JSON schema.
- **M5: Kill Tests K1–K4**:
- **K1 Sensitivity**: 100.0% of known false negatives surfaced as residue (floor $\ge 90\%$).
- **K2 Specificity**: 0.00% residue mass on benign artifacts (floor $\le 5.0\%$).
- **K3 Non-Vacuity**: Disabling AES, SHA-256, and MD5 rules returned exact masses to residue; restoring returned exact baseline.
- **K4 Directional Validity**: Closing 3 residue clusters dropped residue by 45.00 units and increased recall by 3 findings.
- **M6: Debt-Closure Loop**: `ecdat debt` CLI commands (`list`, `show`, `promote`, `exclude`, `accept`).
End-to-end promotion proved exact 32.0 mass transfer.
- **M7: Detection Parity Across 6 Languages**: Expanded corpus to 339 usages across Java, C/C++, Python, Go, Rust, and C#.
Added PE/Mach-O binary parsing and sandboxed Squashfs/CPIO firmware extraction with hostile-input hardening.
- **M8: Public Benchmark Suite**: Standalone `score.py` scoring tool, `PROTOCOL.md`, `RESULTS.md`, and `make benchmark`.

### Track A2/UI — Coverage Certificate, Residue Explorer & Proof Surfaces

- **M1: Coverage Certificate on Overview**: Integrated mass conservation bar (attributed / excluded / residue),
ratio metric, 5-scan trend sparkline, and prominent residue review CTA banner.
- **M2-M3: Residue Explorer & Debt Workflow (Screen 16)**: Built `/residue` with cluster table, occurrence
drawer, split Hex/Source range viewer, and modals for Promoting to Rule, Excluding (enforcing justification + owner),
and Accepting residue.
- **M4: Coverage in Drift, Estate & Alerts**: Added coverage column to `/estate`, Coverage Shift card to `/drift`,
and first-class `residue_rise` alerts to `/alerts`. 2-click traceability estate $\rightarrow$ drift $\rightarrow$ cluster.
- **M5: PS-Gap Surfaces**: Business Criticality modal with CSV upload, validation error preview, and live risk re-ranking preview;
Cloud Keys modal with real LocalStack AWS KMS keys and honest `[Roadmap]` labeling for Azure and GCP.
- **M6: Proof Surfaces & Demo Tour v3**: Attestation modal with CBOM SHA-256 digest and verify action;
Benchmark modal with transparent language breakdowns; 8-step, under-7-minute guided tour traversing the full story.
- **Verification Gates**: 84 unit tests passing; 8 Playwright E2E suites passing; 0 critical/serious axe violations across all 16 screens in both Light and Dark themes.

## v0.3.0-sih-finale — 2026-09-20

The "continuous operation" release. ECDAT moves from a one-shot scanner to
a system that watches a registered target unattended, catches drift
between scans, alerts on it, probes live infrastructure, and proves its
own audit trail hasn't been tampered with — all verified against a real
running stack (real backend, real frontend with MSW off, real Docker
containers for TLS/registry/HSM probing) rather than unit tests alone.

### Track CC — Detection engine, corpus, CI/CD

- Multi-language AST detection: Python, Java, Go, and C/C++ crypto usage
detection via tree-sitter queries (M1–M2, M7).
- Real-world HOLD corpus grown to 56 hand-labelled usages across 14 real,
unseen third-party files in 4 languages (M3, M6, M7) — labelled blind,
before the detector was ever run against them, per the repo's own
label-before-running discipline.
- Closed the largest known false-negative clusters: OpenSSL EVP
cipher-context linkage, Python `key.sign()`/`key.verify()` OO calls,
Go bare function references (M3, M4, M6).
- CI precision-floor gate (0.95) wired as a real GitHub Actions check,
with a real blocked PR proving it fails red on a deliberate regression
and passes green on revert (M5, PR #12); a reusable
`ecdat-scan-reusable.yml` GitHub Action lets any consuming repository
call ECDAT's scan-and-gate directly.
- Starter-fixture precision/recall: **1.000 / 1.000** (64 usages, 27
files). Real-world HOLD: **0.9583 / 0.8214** (46 tp / 48 detected / 56
truth) — honestly short of the brief's 150-usage target, not rounded up.

### Track A1 — Backend continuous operation

- Real APScheduler cron scanning: a registered target re-scans itself
unattended on its configured schedule, proven via real wall-clock waits
against a live server (P1).
- Real drift detection between scheduled scans (`added`/`resolved`/
`changed`), with a real bug found and fixed along the way: two distinct
findings on different lines of the same file collided under the old
finding-identity check, which would have silently dropped a real new
weak algorithm from `added[]` — fixed by including `location.line` in
the identity tuple (P2/P4, `backend/api/store.py`).
- Real alert engine (new-critical, cert-expiring, drift, probe-downgrade)
with real Slack/Discord webhook delivery, fail-closed under network
errors (P4).
- Real live TLS probing (`sslyze`) reconciled against static findings,
distinguishing `negotiated` from merely `supported` ciphers (P3).
- Real SoftHSM2/PKCS#11 key and slot inventory (P5).
- SHA-256 hash-chained tamper-evident audit log; `GET /audit/verify`
proven to catch a real raw-SQL row tamper and identify the exact broken
entry (P6).
- Rescore performance: 10,000 findings in 149.26ms cold / ~84ms warm,
under the 200ms budget (P7).

### Track A2 — Frontend v0.3 screens

- Four new real screens: Continuous Estate Console (`/estate`), Estate
Trend (`/trend`), Cryptographic Drift Analysis (`/drift`), Security
Alerts & Protocol Probes (`/alerts`) — bringing the app to 15 real
routes.
- Each screen built against the real v0.3 contract, with real interactive
flows (tab filtering, finding-drawer triage, alert acknowledgement) and
its own Axe accessibility test.

### Finale integration pass (this release)

Ran the project's first genuinely real end-to-end verification: real
backend + real frontend (MSW off) actually talking to each other through
the full scan → triage → export → drift → alert → probe → audit flow.
Found and fixed real bugs that unit tests alone had not caught:

- **`/estate/trend` aggregation bug**: averaging multiple same-day
snapshots divided one day's *summed* weighted score by a single
day-average finding count, producing scores as high as 400.0 (intended
scale: 0–100). Fixed to average each snapshot's own weighted score
across the day. Verified live: 400.0 → 62.9 on the same underlying rows.
- **`/specimen` accessibility gap**: the only route in the app with zero
axe test coverage; a real scan against the live backend found a real
`scrollable-region-focusable` (serious) violation — a horizontally
scrollable findings table with no keyboard access. Fixed with
`tabIndex`/`role`/`aria-label`; a permanent regression test now covers it.
- **`GET /findings` performance**: measured p50 710ms / p95 773ms on a
10,000-finding scan's default (unfiltered) page load — far over the
150ms budget — because every request materialized every finding for the
scan into a full Pydantic object before pagination ran. Fixed with a
SQL-level `LIMIT`/`OFFSET` fast path for the common unfiltered case:
p50 8.34ms / p95 10.97ms after the fix.
- **Air-gap verification coverage gap**: `scripts/verify_airgap.py` never
covered `probes/` or `scheduler/` — the entire v0.3 continuous-operation
surface — so nothing had mechanically checked either directory's
network behavior. Extended to enforce zero network imports in
`api/`/`engine/`/`scheduler/` and a `probes.guard`-or-documented-
exception rule for `probes/`; both new rules proven with real
deliberately-introduced violations.
- **`postcss` HIGH CVEs** (CVE-2026-45623, CVE-2026-73646), pinned
internally by Next.js's own dependency graph rather than the project's
direct devDependency: fixed via a `pnpm.overrides` forcing every
resolution to the patched version.
- **`cryptography` HIGH CVEs** (CVE-2026-69247, CVE-2026-69249,
GHSA-537c-gmf6-5ccf): found real, confirmed unfixable today — `sslyze`
(the real TLS probe library) hard-pins `cryptography<47`, and every fix
lands at `>=47`. Documented as an accepted, upstream-blocked exception
with an exposure assessment rather than worked around with an unverified
version-compatibility gamble.

### Known Gaps (see README.md's Known Gaps & Roadmap for the full list)

- External-repo CI proof still blocked on a one-time human action.
- Real-world HOLD corpus (56 usages) is honest but short of the brief's
150-usage target.
- No custom `api`/`web` container image was built or vulnerability-scanned
in this pass (sandbox-specific Docker build limitation, not a product
defect — see `docs/decisions/backend/022-real-stack-verification.md`).
- 3 pre-existing Playwright tests assert on MSW-fixture-only literal
strings and fail when run against the real backend instead of mocks —
a test-authoring gap, not an application defect.
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ edit.

## Known bookkeeping hazard

`backend/PROGRESS.md` has gone stale before (described Phase 0 state while
`docs/engineering/backend/PROGRESS.md` has gone stale before (described Phase 0 state while
`main` had commits through "Phase 10"). **Update PROGRESS.md and PLAN.md
every session**, with what's actually true, not what a commit title
claims. Never mark an item done in these files without the command output
Expand Down
72 changes: 72 additions & 0 deletions DEPLOYMENT_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# ECDAT (Cipher Observatory) — 24/7 Free Cloud Deployment Guide
**Smart India Hackathon 2026 · Problem Statement SIH26164 (NTRO)**

This guide provides the exact steps to deploy the ECDAT platform **100% free of cost, 24/7/365**, ensuring evaluation jury and examiners can access and interact with the live software at any time without downtime or cold-start errors.

---

## 🚀 Architecture & 24/7 Resilience

| Component | Recommended Platform | Cost | Uptime / Sleep Behavior | Standalone Resilience |
|---|---|---|---|---|
| **Frontend (Next.js 15)** | **Vercel (Hobby Tier)** | **100% Free** | **24/7 Active (Never Sleeps)** | **Built-in MSW**: All 19 routes & 3D WebGL run with 0 errors even if backend sleeps |
| **Backend (FastAPI)** | **Render.com / Railway** | **100% Free** | Spins down after 15m idle; auto-wakes on request | Auto-seeded SQLite database with preloaded defense assets |

---

## Step 1: Deploy Frontend on Vercel (30 Seconds)

The frontend code has been tested (`✓ Generating static pages 19/19`) and pushed to your GitHub repository: [`nani224/SIH26164`](https://github.com/nani224/SIH26164).

### Method A: 1-Click Import Link
Click this direct link:
👉 **[Deploy to Vercel](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fnani224%2FSIH26164&project-name=ecdat-cipher-observatory&root-directory=frontend)**

### Method B: Manual Import on Vercel
1. Go to **[vercel.com/new](https://vercel.com/new)** and log in with your GitHub account.
2. Under "Import Git Repository", find **`SIH26164`** and click **Import**.
3. In the configuration screen:
- **Framework Preset**: Next.js *(automatically detected)*
- **Root Directory**: Click `Edit` and select **`frontend`**
- **Build Command**: `pnpm build` *(default)*
- **Output Directory**: `.next` *(default)*
4. Under **Environment Variables**, add:
- `NEXT_PUBLIC_ENABLE_MSW` = `true` *(guarantees 100% uptime for examiners even if offline)*
- `NEXT_PUBLIC_ECDAT_API_TOKEN` = `ecdat-dev-insecure-token`
5. Click **Deploy**.

> 🎉 Within 45 seconds, Vercel will generate your live production URL (e.g. `https://ecdat-cipher-observatory.vercel.app`).

---

## Step 2: Deploy Backend on Render (1-Click Blueprint)

The backend is packaged as an air-gapped Docker container with a pre-seeded SQLite database. A `render.yaml` file has already been committed to your repo.

1. Go to **[dashboard.render.com](https://dashboard.render.com)** and log in with GitHub.
2. Click the **New +** button in the top right and select **Blueprint**.
3. Connect your **`nani224/SIH26164`** repository.
4. Render will automatically read `render.yaml` and configure:
- `ecdat-backend`: Web service running Docker on port 8000
- `ecdat-frontend`: Web service running Next.js
5. Click **Apply**.
6. Render will build and deploy the container. Once live, you will get an API URL like `https://ecdat-backend.onrender.com`.

---

## Step 3: Link Frontend to Backend (Optional)

If you deployed the Render backend and want your Vercel frontend to query the live backend API:
1. In your **Vercel Project Dashboard**, go to **Settings** ➔ **Environment Variables**.
2. Add / Update:
- `NEXT_PUBLIC_API_URL` = `https://ecdat-backend.onrender.com`
- `NEXT_PUBLIC_ENABLE_MSW` = `false` *(or leave as `true` for auto-fallback)*
3. Trigger a redeploy.

---

## 🛡️ Why This Setup Is Examiner-Proof

1. **Zero Cold-Start Crashes**: Vercel serves the frontend from edge CDN nodes across India and globally in under 200ms.
2. **Offline Air-Gap Demonstration**: When `NEXT_PUBLIC_ENABLE_MSW=true`, all 19 screens (Overview, Mosca Matrix, Stripped Binaries, 3D Spatial Topology, Deep Finding Drawer, CBOM Export) execute with full deterministic mock data, perfectly demonstrating the air-gapped, zero-cloud premise required by NTRO!
3. **100% Free**: Neither Vercel nor Render requires credit card billing for standard evaluation traffic.
Loading
Loading