Skip to content

feat: Milestone 0.9 (+ 1.0 groundwork) — runnable, integrable, operable - #9

Merged
asharahmed merged 7 commits into
feat/0.8-trustworthyfrom
feat/0.9-runnable
Jul 17, 2026
Merged

feat: Milestone 0.9 (+ 1.0 groundwork) — runnable, integrable, operable#9
asharahmed merged 7 commits into
feat/0.8-trustworthyfrom
feat/0.9-runnable

Conversation

@asharahmed

Copy link
Copy Markdown
Owner

Stacked on #8 (0.8). Continues docs/ROADMAP.md toward 1.0.

0.9 — runnable & integrable

  • 0.9.1 Docker Compose quickstartdocker compose up --build → app + SQL Server, migrated + demo-seeded at localhost:8080. Also fixes a latent Dockerfile bug (missing Infrastructure csproj in the restore graph).
  • 0.9.3 SARIF ingestionPOST /api/ingest/sarif for the universal analysis format (CodeQL/Semgrep/Trivy/Grype).
  • 0.9.4 Accepted-risk with expiry — auto-reopen after the acceptance lapses (vision §7).

1.0 groundwork

  • 1.0.1 Safe deploys — startup fails closed on a migration error in Production (was swallowed); the pipeline gates on /health/ready.
  • 1.0.3 Operator docs — CHANGELOG + configuration reference.

Tests: build clean, 117 unit tests green (+ new SARIF/triage tests); new integration tests (SARIF path, accepted-risk reopen) run in CI on real SQL.

Deferred (documented): 0.9.2 full /api/v1 route versioning needs coordinated client changes + a non-breaking migration — better done deliberately than rushed. Compose wasn't runnable-verified locally (no Docker here); the file parses and the Dockerfile restore graph is complete, but a live up should be smoke-tested.

Review/merge after #5#8.

Vision §7: an accepted risk can now carry an expiry, after which it's
automatically reopened so accepted risks don't linger forever.

- Finding.AcceptedRiskUntil (+ migration); FindingTriage.Apply takes an optional
  future expiry (rejects past dates) and clears it on any other transition;
  FindingTriage.IsExpiredAcceptance predicate.
- SlaReEvaluator reopens lapsed acceptances (→ Open, clears expiry, recomputes
  SLA deadline) before breach detection, and audits it.
- TriageFindingRequest.AcceptedUntil + FindingDto.AcceptedRiskUntil.
- Unit tests for the triage/expiry logic; integration test for reopen-on-expiry.
SARIF 2.1.0 is the universal analysis format (CodeQL/Semgrep/Trivy/Grype …), so
one adapter lets Ravelin ingest almost any scanner — and its own CI's SARIF.

- SarifAdapter maps runs[].results[] → IncomingFinding: identity is (ruleId,
  artifact file, line); severity from the CVSS-style security-severity property
  when present (as CodeQL emits), else the SARIF level; FormatException on a
  non-SARIF payload (can't masquerade as a clean scan).
- POST /api/ingest/sarif (API-key auth, ingest rate-limit), mirroring the other
  native adapters.
- 6 unit tests (CodeQL security-severity, level fallback, rule-level lookup,
  dedup, empty runs, non-SARIF rejection).
Makes 'self-hosted' real: 'docker compose up --build' brings up the app + SQL
Server, migrated and demo-seeded, at http://localhost:8080 — no Azure needed.

- compose.yaml (app built from Dockerfile + mssql/server, healthcheck-gated
  startup, migrate-on-boot, Seed__DemoData=true, Registration__Mode=Open) and
  .env.example (secrets; .env is gitignored).
- Fix a latent Dockerfile bug: the manifest COPY omitted Ravelin.Infrastructure.csproj,
  so 'dotnet restore' (hence 'docker build') would fail. The SDK-container deploy
  path never exercised the Dockerfile, so this went unnoticed.
- README: Docker Compose quickstart as the primary local path.

NOTE: could not run 'docker compose up' in this environment (no Docker); the
compose file parses and the Dockerfile restore-graph is now complete, but a live
'up' should be smoke-tested.
- Startup no longer swallows a migration failure in Production: a failed/partial
  MigrateAsync now fails startup (fail closed) so the app never serves against a
  mismatched schema. Seeding stays best-effort. (Non-Production still logs and
  continues, so local dev without a DB doesn't hard-crash.)
- Azure pipeline Deploy stage polls /health/ready after rolling the image and
  fails the deploy if the new revision doesn't become healthy — a bad deploy is
  signalled instead of silently serving errors (previous revision is retained).
- CHANGELOG.md (Keep a Changelog): Unreleased 0.8/0.9/1.0 work + a summary of
  what shipped in the initial build.
- docs/CONFIGURATION.md: every setting, its default, and whether it's a secret —
  the operator reference a 1.0 needs.
Infra hardening from the code review (applied via terraform apply / re-running
bootstrap by the operator):

- CI/CD identity dropped from RG Contributor to a custom role scoped to the one
  Container App (read/write + revisions), so a compromised pipeline can't delete
  SQL, read storage keys, or tear down the app/Key Vault. AcrPush kept.
- bootstrap-tfstate.sh enables blob versioning + soft-delete on the state account
  (which holds every secret in plaintext) so it survives an accidental
  overwrite/delete. Network default-deny / shared-key-disable left out (need
  backend-auth coordination to avoid locking Terraform out).

terraform validate: clean.
@asharahmed
asharahmed merged commit ab308d7 into feat/0.8-trustworthy Jul 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant