Commit Graph

8 Commits

Author SHA1 Message Date
knacky
76f8443ac2 docs: sprint 2 surface in docs/api.md + D-015/D-016/D-017 + changelog
- `docs/api.md` extended with the sprint-2 surface: pagination envelope
  conventions, engagement members (GET/POST/DELETE), users (GET paginated
  with `?type=`, POST, PATCH, DELETE-soft), audit log viewer with its
  five filters. Anti-enumeration semantics (404 on foreign members) made
  explicit. Drive-by fix: `/engagements<eid>` → `/engagements/<eid>`.
- `tasks/spec-decisions.md` logs the three sprint-2 decisions verbatim:
  - **D-015** USER_MANAGE permission (wording from spec-analyst).
  - **D-016** pagination envelope shape (`{items, total, page, page_size}`).
  - **D-017** `engagement_member.role` stays a free-form label.
- `CHANGELOG.md` summarises the sprint with hashes / behaviours / decisions.
2026-05-23 15:53:45 +02:00
knacky
dd5c508b04 fix(backend): JSON error envelope for every HTTPException + strict_slashes=False
Some checks failed
ci / backend (lint + typecheck + unit tests) (push) Failing after 0s
ci / frontend (lint + typecheck + build + unit tests) (push) Failing after 1s
Two issues spotted by ux-frontend consuming docs/api.md against the actual
code path:

1. `flask.abort(...)` returned the Werkzeug HTML error page for 400/403/404/
   422/etc. — only the 401 paths going through `api_error()` and the
   Flask-Login `unauthorized_handler` honoured the `{error, message}`
   envelope the contract promised. The frontend's `ApiClientError.body`
   parser was forced to fall back to a raw string, and the 422 case
   could not surface Pydantic per-field errors.

   Fix: register `@app.errorhandler(HTTPException)` that serialises every
   `HTTPException` to the same JSON envelope. 422s gain a `details: [...]`
   field holding the Pydantic `errors()` list (`loc` / `msg` / `type`),
   matching the shape now documented in `docs/api.md`.

   A `_HTTP_ERROR_CODES` map maps statuses to stable snake_case codes
   (`bad_request`, `not_found`, `method_not_allowed`,
   `validation_error`, `forbidden`, `internal_error`, ...). Unknown
   statuses fall back to `http_error`.

   `description` is `cast(object, ...)` because the Werkzeug stub pins it
   to `str | None` while `flask.abort(..., description=<list>)` is the
   officially supported way to smuggle a Pydantic errors list to the
   handler.

2. `@bp.get("")` on the engagements blueprint produced `/api/v1/engagements`
   (no slash). Hitting it with a trailing slash issued a 308 redirect,
   and some browsers drop the session cookie across that hop.

   Fix: `app.url_map.strict_slashes = False`. Both forms now match the
   same handler without redirect.

5 new integration tests cover the new envelope shape (422 with details,
unknown 404, malformed-JSON 400) and the dual-slash matching. `docs/api.md`
rewritten to reflect the table of stable codes, the `details` shape, and
the no-trailing-slash convention. `CHANGELOG.md` gains a follow-up entry.

Verification: ruff check / mypy --strict / pytest tests/unit all green
(61 unit + 5 new integration).
2026-05-23 04:33:23 +02:00
knacky
dd321c2cd0 docs: add api.md contract for sprint 1 + update changelog
- docs/api.md: contract the frontend consumes — base URL, auth transport
  (Flask session cookie, credentials: include), uniform error envelope,
  MA6 tenant-scope behaviour (404 not 403), per-endpoint shape for
  /auth/{login,logout,me} and /engagements GET/POST/GET-by-id, plus a
  worked example walking through CLI bootstrap → login → POST engagement →
  list → logout.
- CHANGELOG.md: sprint-1 entry summarising the three endpoints, the dev-
  only CORS, the AuthUser extension, the audit rows, and the test
  coverage.
2026-05-23 04:22:03 +02:00
knacky
df6294ed7b docs: align doc references with compose.yml rename (code-reviewer M1)
Three docs still referenced the old docker-compose.yml path. Replace
with compose.yml so a future reader cloning at this hash finds the
file at the documented path.

- CHANGELOG.md:31 — backend skeleton recap line.
- docs/architecture.md:28 — deployment artifacts note (D-010 scope).
- tasks/todo.md:9 — B0.1 task description.

Also adds a "CI follow-ups (sprint 1+)" section to tasks/todo.md
capturing the 3 MINOR + 6 NIT deferred from code-reviewer's review
of chore/podman-and-ci, plus a FERNET-KEY tracker for the secret
provisioning before c2_credential.config_fernet (D-004) is wired.
2026-05-22 19:49:16 +02:00
knacky
e77ca906d4 docs(backend): track sprint-0 follow-ups + flag integration migration gap
- `tasks/todo.md`: B0.5 description updated (re2 hard dep, no fallback);
  add a "Backend follow-ups (sprint 1+)" section with M1-M7 + N1-N6 from
  the code-review verdict.
- `CHANGELOG.md`: backend skeleton bullets refreshed (no re fallback,
  streaming blob store, audit + scope on CRUD, 56 unit tests); new
  "Code-review remediation" subsection lists B1 / MA1-MA6 / N4 / N6 / M8
  with one-line rationale each.
- `tests/integration/conftest.py`: leave `db.create_all()` in place but
  add an inline TODO (N6) pointing at the Alembic switchover that will
  exercise the F11 seed + audit-log role grants in CI.
2026-05-22 05:25:04 +02:00
knacky
887182cfd7 docs: update CHANGELOG + tasks for the backend skeleton sprint 0
- CHANGELOG.md: detail every B0.1..B0.8 deliverable + spec deltas
  D-008 (ttp_version coexists), D-009 (audit hash chain v1),
  D-010 (no type_annotation_map on declarative base).
- tasks/todo.md: tick every B0.x item.
- tasks/spec-decisions.md: log D-008, D-009, D-010 alongside the
  pre-existing D-001..D-007.
2026-05-21 20:39:06 +02:00
knacky
4ecf4b0b0e chore: tighten gitignore, align README stack, formalize D-010 (Ansible)
- .gitignore: add Keycloak/Mythic/Fernet secret patterns (pfx, p12, token, kdbx,
  credentials.json, secrets.json, service-account*.json), MSVC artifacts
  (lib, exp, idb, ilk, tlog), dedup dist/build/ between Python and Node blocks.
- README.md: align Storage line on H38 (testcontainers Postgres for Postgres-
  specific behavior, incl. unit tests of audit log / RBAC / write-only role).
- README.md: align Deploy line on D-007/D-010 — Docker + Ansible playbook,
  reverse proxy explicitly out-of-Mimic.
- README.md: add proprietary internal use notice.
- CHANGELOG.md: convert markdown link to inline URL (no dangling reference).
- tasks/spec-decisions.md: add D-010 (Ansible for deployment playbook).

Addresses code-reviewer M1/M2/M3 + N2/N3/N4/N6 on commit 047583e.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 20:16:40 +02:00
knacky
047583eb9c chore: bootstrap repo skeleton with sprint 0 plan
- .gitignore (Python, Node, RT/maldev hygiene, secrets)
- README.md (project framing, stack, conventions, status)
- CHANGELOG.md (team kickoff decisions Q1/Q2/Q3, T2/T3/T4, auth strategy)
- tasks/spec-decisions.md (D-001..D-007 arbitrations on top of frozen spec)
- tasks/todo.md (sprint 0 backlog: B0.* / F0.* / S0.* / R0.*)
- tasks/lessons.md (empty, populated as work progresses)
- backend/ frontend/ docs/ scaffolding

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 20:10:47 +02:00