feat/l-1-flow-scaffolds #2

Merged
hibryda merged 3 commits from feat/l-1-flow-scaffolds into main 2026-05-17 21:05:17 +02:00
Owner
No description provided.
Authors qa-rig flow scaffolds for the 19 happy-path Stage B parity flows
documented in <meta-repo>/docs/program/30-stage-c-qa-rig-expansion.md.
Each TOML carries:

- [meta] block with name + type + base_url + tranche-coverage tags
- [setup] shell pointer to scripts/stage-a-demo-up.sh
- [storage_state] block where applicable (adult-1.json / child-1.json)
- 3-5 placeholder [[steps]] with action=navigate/expect_text/expect_no_errors
- TODO markers identifying where domain-specific step authoring lands at
  the corresponding Stage B phase

Flows (all 19 ship as scaffolds; full step authoring lands per Stage B
phase ownership):

- 02 OAuth Google sign-in (L1 identity)
- 03 OAuth Apple sign-in (L1 identity)
- 04 parent-child handoff on same device (L1 identity + L5-T1 family)
- 05 parent creates task assigns to child (L5-T4 calendar/tasks)
- 06 child accepts task; parent notified (L5-T4 + L5-T5 + L3+ realtime)
- 07 parental-control toggle evicts child from chat (post-S2b v6 server-side subs)
- 08 FlowCoach streaming response (L5-T6 chatbot + L3+ realtime)
- 09 family-chat-v2 multi-participant (L5-T1 family chat v2)
- 10 calendar event with weekly recurrence (L5-T4)
- 11 diary entry with emotion tag (L5-T2 diary)
- 12 web subscription via Stripe (L5-T3 subscription)
- 13 mobile subscription via RevenueCat (L5-T3, S5-dependent)
- 14 subscription restore on new device (L5-T3)
- 15 push notification fan-out (L5-T5 notification)
- 16 parental-control change forces UI re-render (Tag 700 SECONDARY path)
- 17 mobile reconnect burst (L4b Capacitor + L3+ realtime)
- 18 admin family-overview (L7 admin-query-service)
- 19 OAuth concurrent same-idempotency-key (L1 identity load)
- 20 token refresh under load (L1 identity load)

Schema constraints:
- All flows use meta.type='browser' (TIER 1 limit). Flows requiring
  type='two-browser' / 'load' / 'mobile-simulated' carry inline TODO
  markers calling out the TIER 6+ extension.
- admin-1.json doesn't exist in mock-data; flow 18 placeholder uses
  adult-1.json with TODO to swap once admin storage state is generated.

Per rule 57 (BPMN-first): BPMN graph generation deferred until qa-rig
gains BPMN-from-TOML codegen support.

All 24 flows (1 existing + 19 new + 4 failure-mode in next commit) pass
tests/test_flows_validate.py schema check. Full pytest suite: 85/85 green.
feat(flows): L-1 scaffolds for 4 failure-mode flows (30-33)
Some checks failed
qa-rig CI / ruff (pull_request) Failing after 4s
qa-rig CI / pytest (pull_request) Successful in 7s
qa-rig CI / live-k3d smoke (pull_request) Has been skipped
e27f49dbf7
Authors qa-rig scaffolds for the 4 failure-mode flows mandated by
v2 hypertribunal-codex Action Item #6 + ADR-0006 (qa-rig parity
baseline = 19-24 frozen flows incl. 4 failure-mode):

- 30 SPIRE Agent down for 60s; existing connections survive on cached
  SVIDs; new connections degrade to fallback ticket pool
  (per ADR-0002 §3.4); alert fires.
- 31 Centrifugo replica force-recreated mid-session; centrifuge-js
  reconnects <30s; history-on-reconnect replays missed messages with
  zero data loss.
- 32 realtime-service `family` Kafka consumer paused 30s; per-tag-prefix
  circuit breaker isolates lag; notification + chat consumers continue;
  no cross-tag-prefix contamination per ADR-0007.
- 33 identity-service /token/centrifugo returns 503 for 60s; new
  connections served via static fallback ticket pool with degraded:true
  context (per ADR-0002 §3.4); alert fires when pool drops below 1k.

These flows execute against the L0 substrate + L2.5 pilot + L3+ realtime
deployments. Until those infrastructure pieces are deployed, the flows
are scaffolds with TODO markers for the failure-injection mechanism
(chaos-inject pattern, daemonset patch, consumer-group-offset
manipulation, configmap toggle, etc.).

All 4 flows pass tests/test_flows_validate.py schema check. Full pytest
suite: 85/85 green.
Author
Owner

Superseded by round 2.

Show previous round

23 scaffold TOML flows added. Four actionable findings: (1) a systematic storage_state.path bug that will silently break all authenticated flows because ../../ escapes the repo root; (2) five expect_text steps using literal TODO_* values that will produce permanent CI failures, contrary to the expect_no_errors pass-through convention used everywhere else in this PR; (3) two OAuth callback URLs that trigger real or crash-prone backend calls rather than clean test failures; and (4) a data-leak verification step whose action does not match its stated acceptance criterion.

Findings (5)

[MAJOR] storage_state.path uses ../../ — likely escapes repo root across all authenticated flows

flows/04-parent-child-handoff.toml:22

Every flow that declares [storage_state] uses path = "../../mock-data/pwa/playwright-storage/<file>.json" (same pattern: flows/05 line 20, 06 line 20, 07 line 21, 08–09 line 21, 10–16 line 21, and likely 17–20). If the FlowSpec runner resolves path relative to the TOML file location (flows/), then ../../ ascends two directory levels — one above the repo root — and the file will never be found. If resolved relative to CWD (repo root), ../../ still escapes the repo. The correct relative path from flows/ to a sibling mock-data/ directory is ../mock-data/…; from repo root it is simply mock-data/…. Either (a) correct every occurrence to path = "../mock-data/pwa/playwright-storage/<file>.json", or (b) add a note to CONTRIBUTING.md documenting the runner's path-resolution rule and adjust the prefix accordingly. Without this fix, every authenticated flow silently starts without Playwright storage state and runs as an unauthenticated user, making all auth-dependent assertions misleading rather than correctly failing.

[MAJOR] expect_text steps with TODO_* literal text values will always fail in CI

flows/02-oauth-google-signin.toml:43

Five flows use action = "expect_text" with text values the application will never render: flows/02 line 43 ("TODO_HOME_GREETING"), flows/03 line 38 ("TODO_HOME_GREETING"), flows/05 line 33 ("TODO_TASK_LIST_HEADER"), flows/07 line 41 ("TODO_LOCKED_STATE_MESSAGE"), flows/09 line 39 ("TODO_TEST_MESSAGE"). The established scaffold convention throughout this same PR is action = "expect_no_errors" as a no-op pass-through (e.g., flows/06 lines 30–33, flows/08 lines 32–41, flows/10 lines 30–35). Change each of these five steps to action = "expect_no_errors" and remove the selector and text keys until the real assertion target is known, or add skip = true at the step level if the FlowSpec schema supports it.

[MINOR] code=TEST_PLACEHOLDER in Google OAuth callback URL triggers a real outbound token-exchange call

flows/02-oauth-google-signin.toml:35

url = "/oauth/callback/google?code=TEST_PLACEHOLDER" will cause the identity-service backend to attempt POST https://oauth2.googleapis.com/token with a syntactically plausible but rejected code. This is not a test-assertion failure — it is an outbound network request that (a) may hang for tens of seconds in CI environments with restricted egress to Google, blocking the entire run, and (b) increments Google API error-rate quota on every execution. Add a prerequisite step that registers an HTTP mock for the identity-service's Google token endpoint (e.g., action = "register_mock" if FlowSpec supports it), or add skip = true / enabled = false to this step until the mock layer is wired. Document which approach the FlowSpec supports so flows/03 can follow the same pattern for Apple.

[MINOR] id_token=TODO_MOCK_JWS will cause a synchronous JWS parse failure in the identity-service handler

flows/03-oauth-apple-signin.toml:31

url = "/oauth/callback/apple?id_token=TODO_MOCK_JWS" passes a value that JWT/JWS libraries reject before the HTTP handler can write a response: TODO_MOCK_JWS is not a valid base64url-encoded compact serialization. Unlike the Google code exchange (which fails at the token-endpoint call), Apple id_token validation is synchronous in the request path. If the identity-service does not wrap Apple JWS parsing in a recovery middleware, the handler may panic or close the connection without writing an HTTP status, causing the FlowSpec runner to see a connection-reset rather than a clean 4xx. Apply the same mock-registration or skip = true guard described for flows/02 line 35.

[MINOR] expect_no_errors does not verify DOM-level parent-data isolation as the acceptance criterion requires

flows/04-parent-child-handoff.toml:52

The acceptance criterion on line 11 states "zero parent-data leakage post-handoff". The step at lines 51–52 (action = "expect_no_errors") only detects JS console errors; parent data rendered in the child session's DOM — for example, the adult-1 greeting "Cześć, Anna" asserted on line 34 — would pass this step silently. If FlowSpec supports expect_not_text, add a step immediately after line 52 with action = "expect_not_text", selector = "body", text = "Cześć, Anna". If expect_not_text is not yet implemented, replace the step name with a comment that records the exact selector and negated string (e.g., # TODO: expect_not_text selector=body text="Cześć, Anna") so this placeholder is distinguishable from the generic expect_no_errors scaffolds elsewhere.


round 1 • 2026-05-14T19:49:12.765Z → 2026-05-14T19:54:50.963Z

<!-- im2be-pr-reviewer collapsed --> > _Superseded by round 2._ <details> <summary>Show previous round</summary> 23 scaffold TOML flows added. Four actionable findings: (1) a systematic `storage_state.path` bug that will silently break all authenticated flows because `../../` escapes the repo root; (2) five `expect_text` steps using literal `TODO_*` values that will produce permanent CI failures, contrary to the `expect_no_errors` pass-through convention used everywhere else in this PR; (3) two OAuth callback URLs that trigger real or crash-prone backend calls rather than clean test failures; and (4) a data-leak verification step whose action does not match its stated acceptance criterion. ### Findings (5) #### **[MAJOR]** `storage_state.path` uses `../../` — likely escapes repo root across all authenticated flows _flows/04-parent-child-handoff.toml:22_ Every flow that declares `[storage_state]` uses `path = "../../mock-data/pwa/playwright-storage/<file>.json"` (same pattern: flows/05 line 20, 06 line 20, 07 line 21, 08–09 line 21, 10–16 line 21, and likely 17–20). If the FlowSpec runner resolves `path` relative to the TOML file location (`flows/`), then `../../` ascends two directory levels — one above the repo root — and the file will never be found. If resolved relative to CWD (repo root), `../../` still escapes the repo. The correct relative path from `flows/` to a sibling `mock-data/` directory is `../mock-data/…`; from repo root it is simply `mock-data/…`. Either (a) correct every occurrence to `path = "../mock-data/pwa/playwright-storage/<file>.json"`, or (b) add a note to CONTRIBUTING.md documenting the runner's path-resolution rule and adjust the prefix accordingly. Without this fix, every authenticated flow silently starts without Playwright storage state and runs as an unauthenticated user, making all auth-dependent assertions misleading rather than correctly failing. #### **[MAJOR]** `expect_text` steps with `TODO_*` literal text values will always fail in CI _flows/02-oauth-google-signin.toml:43_ Five flows use `action = "expect_text"` with `text` values the application will never render: flows/02 line 43 (`"TODO_HOME_GREETING"`), flows/03 line 38 (`"TODO_HOME_GREETING"`), flows/05 line 33 (`"TODO_TASK_LIST_HEADER"`), flows/07 line 41 (`"TODO_LOCKED_STATE_MESSAGE"`), flows/09 line 39 (`"TODO_TEST_MESSAGE"`). The established scaffold convention throughout this same PR is `action = "expect_no_errors"` as a no-op pass-through (e.g., flows/06 lines 30–33, flows/08 lines 32–41, flows/10 lines 30–35). Change each of these five steps to `action = "expect_no_errors"` and remove the `selector` and `text` keys until the real assertion target is known, or add `skip = true` at the step level if the FlowSpec schema supports it. #### **[MINOR]** `code=TEST_PLACEHOLDER` in Google OAuth callback URL triggers a real outbound token-exchange call _flows/02-oauth-google-signin.toml:35_ `url = "/oauth/callback/google?code=TEST_PLACEHOLDER"` will cause the identity-service backend to attempt `POST https://oauth2.googleapis.com/token` with a syntactically plausible but rejected code. This is not a test-assertion failure — it is an outbound network request that (a) may hang for tens of seconds in CI environments with restricted egress to Google, blocking the entire run, and (b) increments Google API error-rate quota on every execution. Add a prerequisite step that registers an HTTP mock for the identity-service's Google token endpoint (e.g., `action = "register_mock"` if FlowSpec supports it), or add `skip = true` / `enabled = false` to this step until the mock layer is wired. Document which approach the FlowSpec supports so flows/03 can follow the same pattern for Apple. #### **[MINOR]** `id_token=TODO_MOCK_JWS` will cause a synchronous JWS parse failure in the identity-service handler _flows/03-oauth-apple-signin.toml:31_ `url = "/oauth/callback/apple?id_token=TODO_MOCK_JWS"` passes a value that JWT/JWS libraries reject before the HTTP handler can write a response: `TODO_MOCK_JWS` is not a valid base64url-encoded compact serialization. Unlike the Google `code` exchange (which fails at the token-endpoint call), Apple `id_token` validation is synchronous in the request path. If the identity-service does not wrap Apple JWS parsing in a recovery middleware, the handler may panic or close the connection without writing an HTTP status, causing the FlowSpec runner to see a connection-reset rather than a clean 4xx. Apply the same mock-registration or `skip = true` guard described for flows/02 line 35. #### **[MINOR]** `expect_no_errors` does not verify DOM-level parent-data isolation as the acceptance criterion requires _flows/04-parent-child-handoff.toml:52_ The acceptance criterion on line 11 states "zero parent-data leakage post-handoff". The step at lines 51–52 (`action = "expect_no_errors"`) only detects JS console errors; parent data rendered in the child session's DOM — for example, the adult-1 greeting `"Cześć, Anna"` asserted on line 34 — would pass this step silently. If FlowSpec supports `expect_not_text`, add a step immediately after line 52 with `action = "expect_not_text"`, `selector = "body"`, `text = "Cześć, Anna"`. If `expect_not_text` is not yet implemented, replace the step `name` with a comment that records the exact selector and negated string (e.g., `# TODO: expect_not_text selector=body text="Cześć, Anna"`) so this placeholder is distinguishable from the generic `expect_no_errors` scaffolds elsewhere. --- <sub>round 1 • 2026-05-14T19:49:12.765Z → 2026-05-14T19:54:50.963Z</sub> </details>
fix(flows): apply autonomous-reviewer round-1 findings
Some checks failed
qa-rig CI / live-k3d smoke (pull_request) Has been skipped
qa-rig CI / ruff (pull_request) Failing after 3s
qa-rig CI / pytest (pull_request) Successful in 6s
ee3f5c5eaf
qa-rig#2 reviewer findings addressed:

- flows/02 (Google OAuth) + flows/03 (Apple OAuth): replace
  `expect_text TODO_HOME_GREETING` placeholder assertions with
  `expect_no_errors` (TODO_HOME_GREETING would have made the step
  fail every run since the literal string never renders). Added
  explicit warnings on the OAuth callback steps that the
  TEST_PLACEHOLDER code / TODO_MOCK_JWS id_token will hit the real
  social-login-service (and fail) until a mock-OAuth registration
  helper lands at M-L2 identity carve-out.
- flows/04 (parent→child handoff): replace the weak
  `expect_no_errors` data-leak check with a clearer placeholder
  comment + a TODO that calls out the missing `expect_not_text`
  action in types.py:VALID_ACTIONS.
- flows/05, 07, 09, 18: same TODO_* → expect_no_errors pattern
  with each flow flagged for the milestone that promotes it to
  a real assertion (M-L2 family-service / M-L3 Centrifugo channel /
  admin-rewire).
- README.md: NEW "Path conventions (mock-data)" section explaining
  why `../../mock-data/` IS correct for this rig — qa-rig is
  always a submodule of im2be-mono so the meta-repo-relative path
  resolves to `<meta-repo>/mock-data/`. The reviewer's recommended
  `../mock-data/` would resolve to `<qa-rig>/mock-data/` which
  doesn't exist; meta-repo CLAUDE.md + rule 55 codify this layout.
Author
Owner

im2be-pr-reviewer — round 2

Reviewing PR #2 in affinity-intelligence-rework/im2be-qa-rig
(head ee3f5c5, base main).

No new findings this round.

_Model output was not valid JSON. First 200 chars: Based on the PR diff provided (the truncated portion beyond flow 13 is not accessible for direct file reads — findings are scoped to the visible diff only), here is the review output:

{ "summary": "R_


round 2 • 2026-05-14T20:46:09.941Z → 2026-05-14T20:49:53.136Z

# im2be-pr-reviewer — round 2 Reviewing PR **#2** in `affinity-intelligence-rework/im2be-qa-rig` (head `ee3f5c5`, base `main`). **No new findings this round.** _Model output was not valid JSON. First 200 chars: Based on the PR diff provided (the truncated portion beyond flow 13 is not accessible for direct file reads — findings are scoped to the visible diff only), here is the review output: { "summary": "R_ --- <sub>round 2 • 2026-05-14T20:46:09.941Z → 2026-05-14T20:49:53.136Z</sub>
hibryda deleted branch feat/l-1-flow-scaffolds 2026-05-17 21:05:17 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
affinity-intelligence-rework/im2be-qa-rig!2
No description provided.