Skip to content
This repository was archived by the owner on Jul 22, 2026. It is now read-only.

Latest commit

 

History

History
123 lines (105 loc) · 6.97 KB

File metadata and controls

123 lines (105 loc) · 6.97 KB

Progress

Working roadmap for hipo (HK IPO Verify): current status and next steps with their verification gates. Stack, infra, and model-gateway setup live in README.md; full product vision in initial-plan.md; the assignment brief in goal.md.

Focus (2026-07-22) — SUNSET

App decommissioned. The infra/*.tf resources and the three deploy workflows are commented out (not deleted — this repo stays a readable archive). Merging that PR to master makes HCP Terraform plan a full destroy; approve it in the HCP workspace UI. Manual teardown steps are below — a few resources are not Terraform-managed and one (the R2 bucket) must be emptied before the destroy applies.

Sunset teardown — manual steps

Do these around the destroy, in order:

  1. Before the destroy applies — empty R2. Cloudflare refuses to delete a non-empty bucket. Empty hipo-filings (dashboard → R2 → hipo-filings → delete all objects, or wrangler r2 object delete in a loop). If the destroy run fails on the bucket, empty it and re-apply.
  2. Delete the catalog Worker (wrangler-owned, not in Terraform). hipo-catalog script + its cron trigger: wrangler delete --name hipo-catalog (or dashboard → Workers → hipo-catalog → Delete). Terraform only owned its KV + R2 stores.
  3. Approve the HCP destroy run, which tears down: 3 Lambdas + streaming Function URL, ECR repo (images go with force_delete), HTTP API + authorizer
    • routes, 4 log groups, the IAM exec role, the KV namespace, the (now-empty) R2 bucket, the Pages project + its deployments, the hipo.vsh852.com Pages domain + CNAME. The vsh852.com zone is a data source — untouched.
  4. After the destroy — revoke/remove what Terraform never held:
    • GitHub repo secrets (Settings → Secrets → Actions): CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID, CATALOG_KV_NAMESPACE_ID, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, ECR_REPOSITORY_URL, the three *_LAMBDA_FUNCTION_NAME, VITE_CATALOG_BASE_URL, VITE_API_BASE_URL.
    • The deploy IAM user (the ECR-push + Lambda-update access key) in AWS IAM.
    • Rotate/revoke the app's live keys: the Cloudflare API token, the LLM gateway keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY), and the shared api_key.
    • HCP workspace hipo: after the destroy leaves state empty, delete the workspace (and its sensitive variables) if you're done with it.

Everything below is the pre-sunset record, kept for the archive.

Focus (2026-07-02)

Brief A shipped. The demoable MVP is live in two pieces — the agent backend on Lambda (a bounded analysis loop turning a PHIP into a validated, cited factsheet) and the analyst-workstation SPA on Cloudflare Pages (hipo.vsh852.com). Design spec: Brief A MVP design. Deferred next: multi-model agreement (B), CI eval gate (C), trust alarm (D).

Status — done

The Brief-A MVP is live end to end at hipo.vsh852.com. Stack, infra, and the deploy/ops detail live in README.md and operations.md.

  • Tooling + CI gate. mise run check (ruff, ty, pytest, Biome/Vitest, tf fmt/validate), pinned toolchain, pre-commit, a hook blocking local terraform apply/destroy, and GitHub Actions running the same gates.
  • Infra applied via HCP. CloudWatch, least-privilege roles, KV (hipo-catalog), R2 (hipo-filings), ECR, three Lambdas (hipo-api, hipo-api-authorizer, hipo-api-stream), HTTP API v2 + authorizer, and the streaming Function URL. Both providers authenticate (AWS OIDC, Cloudflare token).
  • LLM gateway client (llm_gateway/client.py): vendor-neutral routing, per-vendor auth, fallback-chain escalation, streaming complete_stream. Opt-in live smoke (mise run models:smoke).
  • Catalog Worker — live. HkexTitleSearchSource + HkexApplicantArchiveSource behind one CatalogSource; CatalogIndex (KV) + FilingStore (R2, sha256); SSRF allowlist. Serves GET /catalog from live KV; filings cache to live R2 on first view; cron refresh on schedule.
  • Analysis tools + schema. packages/contracts (Field, Factsheet, Rejection, AgentTrace/TraceStep; schema_version=202401), parse.py (pdfminer + redaction detection), chunk.py, select.py, validate.py (schema + citation gate → Full/Partial/Rejected). Fixtures: a PHIP (app-108691-1) and an AP.
  • Streaming analysis agent — live. Bounded, code-driven loop in apps/api/hipo_api/agent/ (parse → chunk → select → extract → normalize → validate → interrupt; step cap 8; model only inside extract; always ends at the interrupt). POST /analyze/{id} drives run_agent on a worker thread and yields each event off a queue as it fires — event: step for trace steps, event: thinking for the model's own output tokens, then a terminal event: result/rejected. Served by the separate uvicorn streaming Lambda behind a RESPONSE_STREAM Function URL; the buffered Mangum path is untouched.
  • Analyst-workstation SPA — live (#13, #16). apps/web/ React 19 + Vite + TS on Pages: filing list, four factsheet panels, right-rail trace streaming live over SSE (steps + a live model-output panel), page-level citation popovers that deep-link to the source PDF, three degradation states, persistent boundary banner, dark-mode toggle, key gate, hippo branding + repo link. Brief-A trust components: elapsed timer with a slow-run cue, retry-on-failure, an evidence-coverage card (disclosed-% / cited-% dials via a pure factsheetStats walker), and a JSON export carrying the never-act disclaimer + provenance. Vitest + RTL + axe green.

Next steps

  • Brief B — multi-model extract + agreement/disagreement panel + arbiter on disputes. Schema and trace are built to accept it without rework.
  • Brief C — gold dataset + CI eval gate that goes red on a bad change; one-command Lambda-alias + Pages rollback.
  • Brief D — end-to-end correlation IDs (partly done), no raw text in logs (done), one alarm on trust degradation (citation/schema rejection rate).

Known limits

  • Model access depends on the external LLM gateway (swappable provider); smoke scripts are opt-in / network-dependent, not in CI.
  • Rollback is only half-wired: the API deploy publishes a Lambda version + live alias, but the HTTP API integration still invokes $LATEST, so an alias move is not yet an instant rollback (see operations.md).
  • Recent HKEX window skews toward ETF/fund prospectuses; PHIP is the MVP focus.
  • apps/api/Dockerfile uses COPY --from=ghcr.io/astral-sh/uv:latest; pin to a digest in a later hardening step.

Deferred (data scope)

  • Historical catalog backfill (~2013 onward), GEM board, applicant-JSON submission-revision lifecycle — current catalog is recent + Main Board.
  • D1 instead of KV if the catalog ever needs real queries.