Files
waggle-os/docs/ga/RECONCILIATION-2026-05-30.md
Oleg Maslov 0c3e2ead3b
Some checks failed
Installer Smoke / installer-smoke (push) Has been cancelled
moving
2026-09-02 10:10:29 +02:00

66 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Waggle-OS GA Reconciliation — 2026-05-30
> Baseline: `main @ 5ccfa53` (2026-05-29). This reconciles `PRODUCTION-PLAN.md` Phases 25 against the code after the Phase0/Phase1 security track (AV-1/2/3/5, D1, gates) and the parallel-session Phase7ae + S4 full type-ratchet (`no-explicit-any` 937→0 repo-wide) both landed. The plan was authored **before** that work, so some items are now closed and some plan claims — especially Phase 7d's "light-mode finish" — are corrected against verified evidence below.
## 1. Headline — what genuinely remains for GA
The hard security and supply-chain work is done (drizzle 0.45 migrated and clean; Stripe `billingPeriod` fail-closed validation in place), but **GA is not shippable as-is**: there is a live **CORS suffix-attack vulnerability in the team server** (`packages/server/src/index.ts:46` passes a raw origin array to Fastify CORS instead of the exact-match `corsOriginAllowed()` the local server already uses), a **payment-gate bypass in both Stripe webhook handlers** (checkout.session.completed grants paid tiers without checking `payment_status`), **no real browser/persona E2E or failure-injection coverage**, **deployment manifests missing all Stripe/CORS env vars**, **light mode ~0.6% migrated** (4 status tokens + 5 KG tokens missing for light theme, 60+ files still hardcoded, contrast never visually validated), and **desktop signing + R7-008 updater-signature unfixed** (these are platform-blocked on Windows). The two items the verifiers downgraded from CLOSED→OPEN/PARTIAL (P3-stripe webhook gate, P3-cors) are the most urgent because they are security regressions, not gaps.
## 2. Cluster status matrix
| Cluster | Phase | Final Status | Key Residuals | Evidence |
|---|---|---|---|---|
| P2-e2e | Phase 2 (WS-B) | **PARTIAL** | No Playwright persona journeys; no failure-injection suite; no R3-002 cycle test; CI bypasses npm scripts | `tests/e2e/user-journeys.spec.ts` (generic J1J10 only); `.github/workflows/ci.yml:71` runs `npx playwright test tests/e2e/` directly |
| P3-sign | Phase 3 (WS-C desktop) | **PARTIAL** | Win cert not in CI; mac Developer ID/notarization not in CI; R7-008 empty `signature:""` | `release.yml:56-65,111-121,137/141/145`; `tauri.conf.json`; pilot self-sign scripts exist but manual |
| P3-cli | Phase 3 (WS-C desktop) | **PARTIAL** | `@waggle/cli` missing `files`, `publishConfig`, metadata, `exports` (publishes tests/src) | `packages/cli/package.json:7-9,16-22`; vs fully-configured `hive-mind-cli` |
| P3-deploy | Phase 3 (WS-C web) | **PARTIAL** | Stripe + CORS env vars absent from both deploy manifests; `render.yaml` build path mismatch (`cd app` vs `apps/web`) | `render.yaml:1-63`; `docker-compose.production.yml:16-57`; Dockerfile non-root OK (`:91-115`) |
| P3-stripe | Phase 3 (WS-C web) | **PARTIAL** ⚠️ *(verifier downgraded from CLOSED)* | Webhook handlers grant tiers without `payment_status` check (R1-002 bypass) | `packages/server/src/stripe/webhook.ts:115-126`; `apps/www/app/api/webhooks/stripe/route.ts:98-110` |
| P3-cors | Phase 3 (WS-C web) | **OPEN** ⚠️ *(verifier downgraded from PARTIAL)* | Team server passes raw array to Fastify CORS → suffix attack; deploy `CORS_ORIGIN` unset | `packages/server/src/index.ts:46` vs correct local `index.ts:1912-1920` + `cors-config.ts:57-59` |
| P3-drizzle | Phase 3 (WS-C migration) | **CLOSED** ✓ | None | `packages/server/package.json:32` `drizzle-orm@^0.45.2`; journal v7; commit `fb33ca8`; tsc clean |
| discovered-drift | Discovered §7.5 | **PARTIAL** ⚠️ *(verifier downgraded from CLOSED)* | Stale `packages/core/src/mind/**` paths + hard-coded script paths in deprecated sync workflows | `sync-mind.yml:51,117-118`; `mind-parity-check.yml:35,41,118,170-171` |
| P4-light | Phase 4 (WS-D) | **OPEN** | 4 light status tokens + 5 KG tokens missing; 60+ files hardcoded; contrast never validated | `apps/web/src/index.css:190`; commit `6a3d598` ("Contrast NOT visually validated"); TRUST-REPORT "~0.6% done" |
| P4-a11y-perf | Phase 4 (WS-D) | **PARTIAL** | ComplianceTemplateModal no Escape/focus-trap/labelledby; window controls absent; harvest `contentHash` never computed/passed | `ComplianceTemplateModal.tsx:171-172`; `harvest.ts:409` + `index.ts:1226,1449` call `recordSync` w/ 3 args; `tauri.conf.json:37` |
Legend: ⚠️ = adversarial verifier overrode the original investigator status.
## 3. Per-phase: what's actually left
### Phase 2 (WS-B) — E2E + failure-injection — PARTIAL
The "E2E" that exists is Vitest server-level tests plus generic Playwright UI journeys. None of the plan's persona/failure-recovery intent is met.
- Add Playwright **persona journeys** for researcher, analyst, coder, product-manager, executive-assistant (chat → tool invocation → result), distinct from generic J1J10. The 17-persona coverage that exists is behavioral unit tests in `packages/agent/tests/behaviors/`, not browser journeys.
- Add a **failure-injection suite** (e.g. `tests/e2e/failure-injection.spec.ts`): network-drop mid-stream, capability-missing hard error, traversal-rejected 403, unpaid-tier gate, sidecar-restart.
- Add the **R3-002 circular-dependency test** asserting `@waggle/shared` / `@waggle/server` / `@waggle/agent` / `@waggle/core` form an acyclic import graph (none exists; grep for `R3-002` returns nothing).
- Fix **CI wiring**: `.github/workflows/ci.yml:71` invokes Playwright directly instead of `npm run test:all` / `test:e2e`, so CI and local diverge from the package.json scripts.
- Publish a **persona→journey coverage map** for CI visibility.
### Phase 3 (WS-C) — desktop, web, migration — mixed
**P3-drizzle is genuinely CLOSED** (verifier agreed): 0.44.7→0.45.2 across server/launcher/worker, journal v7, tsc clean, no audit findings — a pure security patch (GHSA-gpj5-g38j-94v9), 42 usage sites verified.
**P3-stripe — verifier OVERRODE CLOSED → PARTIAL.** Commit `27a98f7` correctly fixed `billingPeriod` (R1-003) and atomic writes (R1-011), but the R1-002 payment gate was only added to the `/api/stripe/sync` endpoint, **not the webhook handlers**. Both `webhook.ts:115-126` and `apps/www/.../route.ts:98-110` process `checkout.session.completed` without checking `session.payment_status`, so webhook delivery can grant a paid tier from an unpaid session. **Next action:** add a `payment_status === 'paid'` (or `'no_payment_required'`) guard in both webhook handlers before any tier grant; add a regression test.
**P3-cors — verifier OVERRODE PARTIAL → OPEN (security).** `packages/server/src/index.ts:46` passes `{ origin: config.corsOrigin }` (raw array) to `@fastify/cors`, which does substring/`includes`-style matching — vulnerable to suffix attacks (e.g. `localhost:1420.evil.com`). The local server already does it right at `index.ts:1912-1920` via `corsOriginAllowed()` (`cors-config.ts:57-59`). **Next action:** unify the team server onto the callback-based exact-match `corsOriginAllowed()`; set `CORS_ORIGIN` in both deploy manifests; add a test asserting lookalike-origin rejection. Treat as a release blocker for any team-server deployment.
**P3-deploy — PARTIAL.** `render.yaml` and `docker-compose.production.yml` declare DB/Redis/Anthropic/Clerk but **omit** `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`, `STRIPE_PRICE_*`, and `CORS_ORIGIN`. Non-root Docker user is correctly set (`Dockerfile:91-115`). **Next action:** add the Stripe + CORS env vars (`sync:false`) to both manifests; resolve the `render.yaml:16` build-path mismatch (`cd app` vs package.json `cd apps/web`) — confirm/alias or fix, since it is a latent deploy failure; document that `apps/www` is a separate Next.js deployment.
**P3-sign — PARTIAL (partly platform-blocked, see §4).** `release.yml` passes no signing secrets for Windows or macOS; the updater manifest hard-codes `signature:""` for all three targets (R7-008); pilot self-sign scripts exist but are manual. **Next action (codeable on Windows):** wire Windows EV cert + `TAURI_PRIVATE_KEY`/`TAURI_KEY_PASSWORD` into `release.yml`, add the GitHub Actions secrets, and populate the updater `signature` field from the signing step. Cert procurement (timeline T+14/2026-05-21 start) appears **overdue** with no in-repo evidence.
**P3-cli — PARTIAL.** `bin → dist/.js` routing works and workspace deps resolve, but `@waggle/cli` lacks `files`, `publishConfig.access`, standard metadata (`repository`/`bugs`/`homepage`/`types`/`author`/`keywords`/`engines`), and `exports` — so it would publish tests/src. **Next action:** mirror `hive-mind-cli`'s package.json publishing config.
**discovered-drift — verifier OVERRODE CLOSED → PARTIAL.** The stale `packages/core/src/mind/**` trigger paths in `sync-mind.yml` and `mind-parity-check.yml` won't fire (files moved to `packages/hive-mind-core` on `3b556c0`), but the shell scripts still hard-code stale paths (`mind-parity-check.yml:118,170-171`) and there's no re-activation runbook — inert by accident, not by design. **Next action:** either delete the deprecated workflows or clean the hard-coded paths and add a one-line runbook note.
### Phase 4 (WS-D) — light mode + a11y/perf — OPEN / PARTIAL
**P4-light — OPEN. The Phase 7d "light-mode finish" claim is materially false.** Verified: only `--status-healthy` has a light value (`index.css:190`); `--status-warning/error/info/ai` and `--kg-person/project/concept/org/default` have **no** light variants; 60+ component files still use hardcoded Tailwind classes (e.g. `UserProfileApp.tsx:232,268,279`); commit `6a3d598` explicitly states "Contrast NOT visually validated (no binary build)"; TRUST-REPORT puts it at "~0.6% done". **Next actions:** add the 4 missing status tokens + 5 KG tokens to the light-theme block; migrate hardcoded classes to semantic tokens; run an independent WCAG-AA contrast audit; review the ~13 flagged mid-tone `text-*-300` accents for regression.
**P4-a11y-perf — PARTIAL.** `ComplianceTemplateModal` has `role="dialog"`/`aria-modal` but no Escape handler, no `aria-labelledby`, no focus trap; `TrialExpiredModal`/`UpgradeModal` have Escape + labelledby but only focus-on-mount (no trap). Window min/max/close controls are absent (`tauri.conf.json:37` `decorations=true`, no custom titlebar). Harvest dedup is **half-wired**: `last_content_hash` exists in DDL and `recordSync()` accepts a 4th `contentHash` arg, but all three callsites (`harvest.ts:409`, `index.ts:1226`, `index.ts:1449`) pass only 3 args, so the O(n·500) rescan persists. **Next actions:** add Escape + `aria-labelledby` + a shared focus-trap to all three modals; build the custom Tauri titlebar; compute SHA-256 `contentHash`, pass it at all three callsites, and add the dedup skip on `last_content_hash`.
### Phase 5 — not present in reconciliation set
No Phase 5 clusters were verified in this pass. The plan's Phase 5 items are **unreconciled** here — treat as untracked and re-scope before GA sign-off (do not assume closed).
## 4. Platform-blocked on Windows (cannot be completed in this env)
These require a macOS host and/or real signed binary runtime and are **not codeable here**:
- **R7-008 / macOS signing + notarization** — Developer ID signing and `notarytool` need a Mac; the updater `signature` field cannot be populated with a real signature without an actual signed-build pipeline. (Windows EV signing *can* be wired from here once the cert is procured; only the mac half and live signature generation are blocked.)
- **Binary runtime smokes** — light-mode contrast validation, modal a11y smoke, and window-controls verification that the Phase 7d commit explicitly deferred ("no binary build") need a built desktop binary to observe; they cannot be visually validated in this environment.
## 5. Recommended next workflow
Fix the two security downgrades first as a TDD security pass — **P3-cors exact-match unification + P3-stripe webhook `payment_status` gate** (write failing tests, fix, verify), then run the Phase 2 E2E/failure-injection build-out and Phase 3 deploy-env wiring; defer all macOS-signing/binary-runtime items to a Mac/CI environment.