@terreno/mcp 0.31.0 → 56.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +8 -9
- package/dist/bootstrap.js.map +1 -1
- package/dist/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
- package/dist/docs/upgrades/56.0.0-beta.2.md +59 -0
- package/dist/docs/versioned/next/README.md +2 -0
- package/dist/docs/versioned/next/explanation/roadmap-seed-issues.md +21 -0
- package/dist/docs/versioned/next/how-to/README.md +2 -0
- package/dist/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
- package/dist/docs/versioned/next/implementationPlans/PLAN_INDEX.md +28 -50
- package/dist/docs/versioned/next/implementationPlans/b2b-platform-program.md +3 -2
- package/dist/docs/versioned/next/implementationPlans/comms-abstraction.md +98 -15
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +63 -13
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +65 -12
- package/dist/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +9 -3
- package/dist/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +180 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +126 -0
- package/dist/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +269 -0
- package/dist/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
- package/dist/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
- package/dist/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
- package/dist/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
- package/dist/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
- package/dist/docs/versioned/next/reference/README.md +2 -0
- package/dist/docs/versioned/next/reference/comms.md +132 -0
- package/dist/docs/versioned/next/reference/environment-variables.md +9 -0
- package/dist/docs/versioned/next/reference/syncdb.md +456 -0
- package/dist/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
- package/dist/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
- package/dist/docs/versioned/next/tasks/comms-abstraction.md +29 -16
- package/dist/docs/versioned/next/tasks/comms-adapter-sendgrid.md +17 -7
- package/dist/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +17 -7
- package/dist/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +3 -3
- package/dist/docs/versioned/next/tasks/comms-admin-dashboard.md +52 -0
- package/dist/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +215 -0
- package/dist/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
- package/dist/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
- package/dist/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
- package/package.json +3 -3
- package/src/docs/templates/bootstrap/frontend/app/_layout.template.tsx +1 -1
- package/src/docs/upgrades/56.0.0-beta.2.md +59 -0
- package/src/docs/versioned/next/README.md +2 -0
- package/src/docs/versioned/next/explanation/roadmap-seed-issues.md +21 -0
- package/src/docs/versioned/next/how-to/README.md +2 -0
- package/src/docs/versioned/next/how-to/migrate-rtk-to-syncdb.md +445 -0
- package/src/docs/versioned/next/implementationPlans/PLAN_INDEX.md +28 -50
- package/src/docs/versioned/next/implementationPlans/b2b-platform-program.md +3 -2
- package/src/docs/versioned/next/implementationPlans/comms-abstraction.md +98 -15
- package/src/docs/versioned/next/implementationPlans/comms-adapter-sendgrid.md +63 -13
- package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-sms.md +65 -12
- package/src/docs/versioned/next/implementationPlans/comms-adapter-twilio-verify.md +9 -3
- package/src/docs/versioned/next/implementationPlans/comms-admin-dashboard.md +180 -0
- package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci-research.md +126 -0
- package/src/docs/versioned/next/implementationPlans/migrate-cicd-to-circleci.md +269 -0
- package/src/docs/versioned/next/implementationPlans/rtk-to-syncdb-migration-docs.md +52 -47
- package/src/docs/versioned/next/implementationPlans/syncdb-api-inventory.md +303 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-codegen.md +252 -0
- package/src/docs/versioned/next/implementationPlans/syncdb-local-first.md +468 -420
- package/src/docs/versioned/next/implementationPlans/syncdb-phase-c-design.md +425 -0
- package/src/docs/versioned/next/implementationPlans/terreno-syncdb-2.md +800 -0
- package/src/docs/versioned/next/reference/README.md +2 -0
- package/src/docs/versioned/next/reference/comms.md +132 -0
- package/src/docs/versioned/next/reference/environment-variables.md +9 -0
- package/src/docs/versioned/next/reference/syncdb.md +456 -0
- package/src/docs/versioned/next/superpowers/plans/2026-07-28-admin-mobile-navigation.md +97 -0
- package/src/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md +36 -0
- package/src/docs/versioned/next/tasks/comms-abstraction.md +29 -16
- package/src/docs/versioned/next/tasks/comms-adapter-sendgrid.md +17 -7
- package/src/docs/versioned/next/tasks/comms-adapter-twilio-sms.md +17 -7
- package/src/docs/versioned/next/tasks/comms-adapter-twilio-verify.md +3 -3
- package/src/docs/versioned/next/tasks/comms-admin-dashboard.md +52 -0
- package/src/docs/versioned/next/tasks/migrate-cicd-to-circleci.md +215 -0
- package/src/docs/versioned/next/tasks/rtk-to-syncdb-migration-docs.md +10 -10
- package/src/docs/versioned/next/tasks/syncdb-codegen.md +65 -0
- package/src/docs/versioned/next/tasks/syncdb-local-first.md +434 -117
- package/dist/__tests__/bootstrap.test.d.ts +0 -2
- package/dist/__tests__/bootstrap.test.d.ts.map +0 -1
- package/dist/__tests__/bootstrap.test.js +0 -299
- package/dist/__tests__/bootstrap.test.js.map +0 -1
- package/dist/__tests__/databaseQuery.test.d.ts +0 -2
- package/dist/__tests__/databaseQuery.test.d.ts.map +0 -1
- package/dist/__tests__/databaseQuery.test.js +0 -83
- package/dist/__tests__/databaseQuery.test.js.map +0 -1
- package/dist/__tests__/docsRoot.test.d.ts +0 -2
- package/dist/__tests__/docsRoot.test.d.ts.map +0 -1
- package/dist/__tests__/docsRoot.test.js +0 -59
- package/dist/__tests__/docsRoot.test.js.map +0 -1
- package/dist/__tests__/inferPackages.test.d.ts +0 -2
- package/dist/__tests__/inferPackages.test.d.ts.map +0 -1
- package/dist/__tests__/inferPackages.test.js +0 -35
- package/dist/__tests__/inferPackages.test.js.map +0 -1
- package/dist/__tests__/preload.d.ts +0 -2
- package/dist/__tests__/preload.d.ts.map +0 -1
- package/dist/__tests__/preload.js +0 -12
- package/dist/__tests__/preload.js.map +0 -1
- package/dist/__tests__/prompts.test.d.ts +0 -2
- package/dist/__tests__/prompts.test.d.ts.map +0 -1
- package/dist/__tests__/prompts.test.js +0 -295
- package/dist/__tests__/prompts.test.js.map +0 -1
- package/dist/__tests__/resources.test.d.ts +0 -2
- package/dist/__tests__/resources.test.d.ts.map +0 -1
- package/dist/__tests__/resources.test.js +0 -352
- package/dist/__tests__/resources.test.js.map +0 -1
- package/dist/__tests__/search.test.d.ts +0 -2
- package/dist/__tests__/search.test.d.ts.map +0 -1
- package/dist/__tests__/search.test.js +0 -163
- package/dist/__tests__/search.test.js.map +0 -1
- package/dist/__tests__/tools.test.d.ts +0 -2
- package/dist/__tests__/tools.test.d.ts.map +0 -1
- package/dist/__tests__/tools.test.js +0 -540
- package/dist/__tests__/tools.test.js.map +0 -1
- package/dist/__tests__/upgradeGuide.test.d.ts +0 -2
- package/dist/__tests__/upgradeGuide.test.d.ts.map +0 -1
- package/dist/__tests__/upgradeGuide.test.js +0 -22
- package/dist/__tests__/upgradeGuide.test.js.map +0 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Admin Mobile Navigation Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** On viewports below 768px, replace the admin shell’s fixed sidebar with a hamburger-triggered left slide-over drawer.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Keep navigation content in one shared internal component. `AdminShell` uses `useWindowDimensions` to switch between desktop rail and mobile header + overlay drawer. Drawer closes on backdrop, close button, and nav selection.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** React Native / Expo, `@terreno/ui` (`Box`, `Heading`, `Text`, `IconButton`), bun test + `@testing-library/react-native`.
|
|
10
|
+
|
|
11
|
+
## Global Constraints
|
|
12
|
+
|
|
13
|
+
- Breakpoint: below 768px → mobile; 768px and above → desktop sidebar.
|
|
14
|
+
- Menu style: left slide-over drawer with dismissible backdrop.
|
|
15
|
+
- Accessibility: hamburger labeled "Open navigation menu"; close labeled "Close navigation menu".
|
|
16
|
+
- Do not change public `AdminShellProps` API unless required.
|
|
17
|
+
- Always support React Native Web.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
### Task 1: Failing AdminShell responsive tests
|
|
22
|
+
|
|
23
|
+
**Files:**
|
|
24
|
+
- Create: `admin-frontend/src/AdminShell.test.tsx`
|
|
25
|
+
|
|
26
|
+
**Interfaces:**
|
|
27
|
+
- Consumes: `AdminShell` from `./AdminShell`; mocked `./useAdminConfig` and `expo-router`
|
|
28
|
+
- Produces: failing tests that assert desktop sidebar at ≥768, mobile header below 768, drawer open/close, nav closes drawer, a11y labels
|
|
29
|
+
|
|
30
|
+
- [ ] **Step 1: Write the failing test file**
|
|
31
|
+
|
|
32
|
+
Mock `useWindowDimensions` via a mutable width, mock `useAdminConfig` with a small config (Home + one model), mock `expo-router.router.push`. Assert:
|
|
33
|
+
|
|
34
|
+
1. width 1024 → `admin-shell-sidebar` present; hamburger absent
|
|
35
|
+
2. width 500 → sidebar absent; `admin-shell-menu-button` present with accessibilityLabel "Open navigation menu"
|
|
36
|
+
3. press menu → `admin-shell-drawer` and backdrop appear; close button has "Close navigation menu"
|
|
37
|
+
4. press backdrop / close → drawer gone
|
|
38
|
+
5. open drawer, press Home nav → `router.push` called and drawer closed
|
|
39
|
+
|
|
40
|
+
- [ ] **Step 2: Run tests and confirm failure**
|
|
41
|
+
|
|
42
|
+
Run: `cd admin-frontend && bun test src/AdminShell.test.tsx`
|
|
43
|
+
Expected: FAIL (missing mobile UI / testIDs)
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### Task 2: Implement responsive AdminShell
|
|
48
|
+
|
|
49
|
+
**Files:**
|
|
50
|
+
- Modify: `admin-frontend/src/AdminShell.tsx`
|
|
51
|
+
- Test: `admin-frontend/src/AdminShell.test.tsx`
|
|
52
|
+
|
|
53
|
+
**Interfaces:**
|
|
54
|
+
- Consumes: nav data from `useAdminConfig` (existing)
|
|
55
|
+
- Produces: `MOBILE_BREAKPOINT = 768`; shared sidebar body; mobile header; overlay drawer with backdrop
|
|
56
|
+
|
|
57
|
+
- [ ] **Step 1: Extract shared sidebar body**
|
|
58
|
+
|
|
59
|
+
Create an internal `AdminShellSidebarNav` that receives navigate callbacks, grouped models, scripts, screens, configurationPath, footer, sidebarVariant, and optional `onNavigate` that runs after each nav press (used to close the drawer).
|
|
60
|
+
|
|
61
|
+
- [ ] **Step 2: Wire responsive chrome**
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
const MOBILE_BREAKPOINT = 768;
|
|
65
|
+
const {width} = useWindowDimensions();
|
|
66
|
+
const isMobileLayout = width < MOBILE_BREAKPOINT;
|
|
67
|
+
const [isNavOpen, setIsNavOpen] = useState(false);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Desktop: existing fixed 280px sidebar.
|
|
71
|
+
Mobile: compact header (`admin-shell-mobile-header`) with `IconButton` (`iconName="bars"`, testID `admin-shell-menu-button`) + "Admin" heading; main content full width.
|
|
72
|
+
When `isNavOpen`: absolute full-screen overlay (`admin-shell-drawer`) with backdrop (`admin-shell-drawer-backdrop`) and 280px panel containing close `IconButton` (`iconName="xmark"`, testID `admin-shell-drawer-close`) + shared nav. Close on backdrop, close button, and after navigate.
|
|
73
|
+
|
|
74
|
+
- [ ] **Step 3: Close drawer when resizing to desktop**
|
|
75
|
+
|
|
76
|
+
`useEffect` clears `isNavOpen` when `!isMobileLayout`.
|
|
77
|
+
|
|
78
|
+
- [ ] **Step 4: Run tests**
|
|
79
|
+
|
|
80
|
+
Run: `cd admin-frontend && bun test src/AdminShell.test.tsx`
|
|
81
|
+
Expected: PASS
|
|
82
|
+
|
|
83
|
+
- [ ] **Step 5: Compile and lint**
|
|
84
|
+
|
|
85
|
+
Run: `cd admin-frontend && bun run compile && bun run lint`
|
|
86
|
+
Expected: clean
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Task 3: Manual UI verification
|
|
91
|
+
|
|
92
|
+
**Files:** none (runtime check in example-frontend admin)
|
|
93
|
+
|
|
94
|
+
- [ ] **Step 1:** With backend + `frontend:web` running, open `/admin` as `admin@example.com`
|
|
95
|
+
- [ ] **Step 2:** Narrow viewport below 768 → hamburger header, no fixed sidebar
|
|
96
|
+
- [ ] **Step 3:** Open drawer, navigate, confirm close; widen to ≥768 → sidebar returns
|
|
97
|
+
- [ ] **Step 4:** Capture screenshot evidence under `.devdata/artifacts/`
|
package/src/docs/versioned/next/superpowers/specs/2026-07-28-admin-mobile-navigation-design.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Admin Mobile Navigation Design
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Make the admin shell usable on narrow devices by replacing its fixed 280px sidebar with a hamburger-triggered navigation drawer below 768px.
|
|
6
|
+
|
|
7
|
+
## Responsive behavior
|
|
8
|
+
|
|
9
|
+
- At widths of 768px and above, preserve the existing sidebar and content layout.
|
|
10
|
+
- Below 768px, hide the fixed sidebar and show a compact header with an accessible hamburger button and the Admin label.
|
|
11
|
+
- Opening the hamburger displays the same grouped navigation in a left slide-over drawer above the page.
|
|
12
|
+
- A backdrop covers the remaining page and dismisses the drawer when pressed.
|
|
13
|
+
- The drawer also closes from its close button and after any navigation item is selected.
|
|
14
|
+
|
|
15
|
+
## Component structure
|
|
16
|
+
|
|
17
|
+
Extract the sidebar body into a shared internal component so desktop and mobile render the same links, groups, configuration entry, and footer. `AdminShell` owns responsive width detection and drawer open state. The existing main content, top bar, breadcrumbs, and header actions remain unchanged apart from the added mobile header.
|
|
18
|
+
|
|
19
|
+
## Accessibility
|
|
20
|
+
|
|
21
|
+
- The hamburger button has an "Open navigation menu" label.
|
|
22
|
+
- The drawer close button has a "Close navigation menu" label.
|
|
23
|
+
- Backdrop dismissal is available in addition to the explicit close button.
|
|
24
|
+
- Existing navigation labels and hints remain intact.
|
|
25
|
+
|
|
26
|
+
## Testing
|
|
27
|
+
|
|
28
|
+
Add focused `AdminShell` tests covering:
|
|
29
|
+
|
|
30
|
+
- Desktop sidebar rendering at 768px and above.
|
|
31
|
+
- Mobile header rendering below 768px.
|
|
32
|
+
- Opening and closing the drawer.
|
|
33
|
+
- Closing after selecting a navigation item.
|
|
34
|
+
- Hamburger and close-button accessibility labels.
|
|
35
|
+
|
|
36
|
+
Run the admin frontend test suite, compile, lint, and responsive UI verification.
|
|
@@ -4,55 +4,68 @@ IP: [comms-abstraction](../implementationPlans/comms-abstraction.md)
|
|
|
4
4
|
|
|
5
5
|
## Phase 1 — Package + contracts
|
|
6
6
|
|
|
7
|
-
- [
|
|
7
|
+
- [x] **Task 1.1**: Scaffold `@terreno/comms` workspace package
|
|
8
8
|
- Description: `comms/` package with tsconfig/biome/bun test setup mirroring `feature-flags/`; root workspace entry + `comms:*` scripts
|
|
9
9
|
- Files: `comms/package.json`, `comms/tsconfig.json`, `comms/biome.jsonc`, root `package.json`
|
|
10
10
|
- Depends on: none
|
|
11
11
|
- Acceptance: `bun run comms:compile` and `bun run comms:lint` pass
|
|
12
12
|
- [ ] **Task 1.2**: Provider interfaces and message types
|
|
13
|
-
- Description: `MailProvider`, `SmsProvider`, `PushProvider`, `VerificationProvider`, `SendResult
|
|
13
|
+
- Description: `MailProvider`, `SmsProvider`, `PushProvider`, `VerificationProvider`, `SendResult` (incl. `errorCode`/`errorClass`), `DeliveryEvent`, `CommsHookContext`, `OptOutEvent` per IP
|
|
14
|
+
- Status: base provider/message contracts shipped; `errorCode`/`errorClass`, `CommsHookContext`, and `OptOutEvent` remain
|
|
14
15
|
- Files: `comms/src/types.ts`
|
|
15
16
|
- Depends on: 1.1
|
|
16
17
|
- Acceptance: types compile and are exported
|
|
17
|
-
- [
|
|
18
|
+
- [x] **Task 1.3**: Console adapters
|
|
18
19
|
- Description: dev adapters for all four channels logging via `logger.info`
|
|
19
20
|
- Files: `comms/src/adapters/console.ts` + tests
|
|
20
21
|
- Depends on: 1.2
|
|
21
22
|
- Acceptance: each adapter returns `accepted: true` and logs
|
|
22
23
|
- [ ] **Task 1.4**: `CommsMessage` model + `logSend`
|
|
23
|
-
- Description: delivery log model with five-type pattern, `description` on every field, plugins, static `logSend` that never throws
|
|
24
|
+
- Description: delivery log model with five-type pattern, `description` on every field, plugins, static `logSend` that never throws; dashboard-ready fields (`errorCode`, `errorClass`, `attempts[]`, `attemptCount`, `lastAttemptAt`, `retriedFromId`/`retriedById`, `templateId`, retained `payload`)
|
|
24
25
|
- Files: `comms/src/models/commsMessage.ts` + tests
|
|
25
26
|
- Depends on: 1.1
|
|
26
|
-
- Acceptance: send logging survives a forced model error (logged, not thrown)
|
|
27
|
+
- Acceptance: send logging survives a forced model error (logged, not thrown); attempts append per attempt
|
|
28
|
+
- Status: model and non-throwing `logSend` shipped; dashboard-ready fields remain
|
|
27
29
|
- [ ] **Task 1.5**: `commsService` send facade
|
|
28
|
-
- Description: `sendMail`/`sendSms`/`sendPushToUser`/`startVerification`/`checkVerification`; template render helper; unconfigured-channel behavior (501 in prod, console fallback in dev)
|
|
30
|
+
- Description: `sendMail`/`sendSms`/`sendPushToUser`/`startVerification`/`checkVerification`; template render helper; unconfigured-channel behavior (501 in prod, console fallback in dev); inline retry on `errorClass: "transient"` only
|
|
31
|
+
- Status: send facade, templates, and unconfigured-channel behavior shipped; inline transient retry remains
|
|
29
32
|
- Files: `comms/src/commsService.ts`, `comms/src/templates.ts` + tests
|
|
30
33
|
- Depends on: 1.2, 1.3, 1.4
|
|
31
|
-
- Acceptance: unit tests cover happy path + unconfigured channel in both env modes
|
|
34
|
+
- Acceptance: unit tests cover happy path + unconfigured channel in both env modes; permanent failures do not retry
|
|
35
|
+
- [ ] **Task 1.6**: Lifecycle hooks
|
|
36
|
+
- Description: `beforeSend` (mutate/cancel), `onSend`, `onError`, `onRetry`, `onOptOut`, `onDeliveryEvent` wiring in the facade; every hook wrapped so a throw is logged and never changes the send outcome
|
|
37
|
+
- Files: `comms/src/commsService.ts` + tests
|
|
38
|
+
- Depends on: 1.5
|
|
39
|
+
- Acceptance: one test per hook (fires with correct context) plus one throwing-hook test per hook
|
|
40
|
+
- [ ] **Task 1.7**: Payload retention + redaction
|
|
41
|
+
- Description: `retainPayloadDays` (default 30) storage of rendered payload post-`redactPayload`; expiry cleanup clears `payload` without touching the log row
|
|
42
|
+
- Files: `comms/src/commsService.ts`, `comms/src/models/commsMessage.ts` + tests
|
|
43
|
+
- Depends on: 1.4, 1.5
|
|
44
|
+
- Acceptance: payload stored redacted; expired payload cleared; `retainPayloadDays: 0` stores nothing
|
|
32
45
|
|
|
33
46
|
## Phase 2 — CommsApp + routes
|
|
34
47
|
|
|
35
|
-
- [
|
|
48
|
+
- [x] **Task 2.1**: `PushToken` model
|
|
36
49
|
- Description: model per IP with unique token upsert semantics
|
|
37
50
|
- Files: `comms/src/models/pushToken.ts` + tests
|
|
38
51
|
- Depends on: 1.1
|
|
39
52
|
- Acceptance: duplicate token registration updates the existing row
|
|
40
|
-
- [
|
|
53
|
+
- [x] **Task 2.2**: `CommsApp` TerrenoPlugin
|
|
41
54
|
- Description: options wiring, `getCommsService()` accessor, route mounting on `register()`
|
|
42
55
|
- Files: `comms/src/commsApp.ts` + tests
|
|
43
56
|
- Depends on: 1.5, 2.1
|
|
44
57
|
- Acceptance: plugin registers on `TerrenoApp` and service accessor returns configured providers
|
|
45
|
-
- [
|
|
46
|
-
- Description:
|
|
58
|
+
- [x] **Task 2.3**: Push token routes
|
|
59
|
+
- Description: custom idempotent registration/list/deactivation endpoints plus modelRouter owner read; persisted `userId` scoping
|
|
47
60
|
- Files: `comms/src/routes/pushTokens.ts` + supertest
|
|
48
61
|
- Depends on: 2.2
|
|
49
62
|
- Acceptance: acceptance criteria bullets 2 pass under supertest
|
|
50
|
-
- [
|
|
63
|
+
- [x] **Task 2.4**: Admin delivery explorer
|
|
51
64
|
- Description: `GET /comms/messages` admin-only, paginated, filtered; OpenAPI builder
|
|
52
65
|
- Files: `comms/src/routes/commsExplorer.ts` + supertest
|
|
53
66
|
- Depends on: 2.2
|
|
54
67
|
- Acceptance: non-admin gets 403; filters work
|
|
55
|
-
- [
|
|
68
|
+
- [x] **Task 2.5**: `sendPushToUser` token resolution + pruning
|
|
56
69
|
- Description: resolve active tokens per user; deactivate tokens whose `SendResult` reports permanent failure
|
|
57
70
|
- Files: `comms/src/commsService.ts` + tests
|
|
58
71
|
- Depends on: 2.1, 1.5
|
|
@@ -60,17 +73,17 @@ IP: [comms-abstraction](../implementationPlans/comms-abstraction.md)
|
|
|
60
73
|
|
|
61
74
|
## Phase 3 — Integration + docs
|
|
62
75
|
|
|
63
|
-
- [
|
|
76
|
+
- [x] **Task 3.1**: example-backend registration
|
|
64
77
|
- Description: register `CommsApp` with console adapters; env-gated
|
|
65
78
|
- Files: `example-backend/src/server.ts`
|
|
66
79
|
- Depends on: 2.2
|
|
67
80
|
- Acceptance: backend boots; `/comms/pushTokens` in `/openapi.json`
|
|
68
|
-
- [
|
|
81
|
+
- [x] **Task 3.2**: Reference docs + rules
|
|
69
82
|
- Description: `docs/reference/comms.md`, rulesync source rule, `bun run rules`
|
|
70
83
|
- Files: `docs/reference/comms.md`, `.rulesync/**`
|
|
71
84
|
- Depends on: 2.x
|
|
72
85
|
- Acceptance: `bun run rules:check` passes
|
|
73
|
-
- [
|
|
86
|
+
- [x] **Task 3.3**: CI + publish wiring
|
|
74
87
|
- Description: `comms-ci` workflow; add `@terreno/comms` to `publish-on-tag.yml`
|
|
75
88
|
- Files: `.github/workflows/comms-ci.yml`, `.github/workflows/publish-on-tag.yml`
|
|
76
89
|
- Depends on: 1.x
|
|
@@ -9,21 +9,31 @@ IP: [comms-adapter-sendgrid](../implementationPlans/comms-adapter-sendgrid.md)
|
|
|
9
9
|
- Files: `comms/src/adapters/sendgrid.ts`
|
|
10
10
|
- Depends on: comms-abstraction Phase 1
|
|
11
11
|
- Acceptance: mocked-client tests for text/html/template sends
|
|
12
|
-
- [ ] **Task 1.2**: Error
|
|
13
|
-
- Description:
|
|
12
|
+
- [ ] **Task 1.2**: Error classification
|
|
13
|
+
- Description: HTTP status → `errorCode`/`errorClass` per the IP table (400 permanent, 401/403 config, 429/5xx transient); full response body into `CommsMessage.metadata`; never throws
|
|
14
14
|
- Files: `comms/src/adapters/sendgrid.ts`
|
|
15
15
|
- Depends on: 1.1
|
|
16
|
-
- Acceptance: unverified-sender
|
|
17
|
-
- [ ] **Task 1.3**:
|
|
16
|
+
- Acceptance: unverified-sender (config), bad-address (permanent), and 429 (transient) fixtures assert `errorClass`; permanent skips the inline retry
|
|
17
|
+
- [ ] **Task 1.3**: Dashboard metadata + hooks coverage
|
|
18
|
+
- Description: capture `x-message-id`; `metadata.consoleUrl` Email Activity deep link; `onError` fires with the classified `SendResult`
|
|
19
|
+
- Files: `comms/src/adapters/sendgrid.ts` + tests
|
|
20
|
+
- Depends on: 1.2
|
|
21
|
+
- Acceptance: accepted-send test asserts message id + consoleUrl; failed-send test asserts onError invocation
|
|
22
|
+
- [ ] **Task 1.4**: Peer dep + registration + docs
|
|
18
23
|
- Description: optional peer `@sendgrid/mail`; env-gated example-backend registration with fail-fast; reference + env docs incl. sender-verification checklist
|
|
19
24
|
- Files: `comms/package.json`, `example-backend/src/server.ts`, `docs/reference/comms.md`, `docs/reference/environment-variables.md`
|
|
20
25
|
- Depends on: 1.1
|
|
21
26
|
- Acceptance: boot without key skips registration; compile passes without the SDK installed
|
|
22
27
|
|
|
23
|
-
## Phase 2 — Delivery events (gated on inbound-webhooks)
|
|
28
|
+
## Phase 2 — Delivery events + opt-outs (gated on inbound-webhooks)
|
|
24
29
|
|
|
25
30
|
- [ ] **Task 2.1**: Event Webhook route
|
|
26
|
-
- Description: ECDSA signature verification via inbound-webhooks;
|
|
31
|
+
- Description: ECDSA signature verification via inbound-webhooks; event mapping per the IP table → `DeliveryEvent`; `x-message-id` prefix correlation
|
|
27
32
|
- Files: `comms/src/adapters/sendgrid.ts`, webhook registration
|
|
28
33
|
- Depends on: inbound-webhooks IP
|
|
29
|
-
- Acceptance: signed
|
|
34
|
+
- Acceptance: signed fixtures per event type update `CommsMessage.status` (+ `errorCode` for bounce/dropped); unsigned rejected 401
|
|
35
|
+
- [ ] **Task 2.2**: Opt-out events
|
|
36
|
+
- Description: `spamreport`/`unsubscribe`/`group_unsubscribe` → `OptOutEvent` → consumer `onOptOut`
|
|
37
|
+
- Files: `comms/src/adapters/sendgrid.ts` + tests
|
|
38
|
+
- Depends on: 2.1
|
|
39
|
+
- Acceptance: spamreport fixture fires `onOptOut`; subsequent `dropped` classified `permanent`
|
|
@@ -9,21 +9,31 @@ IP: [comms-adapter-twilio-sms](../implementationPlans/comms-adapter-twilio-sms.m
|
|
|
9
9
|
- Files: `comms/src/adapters/twilioSms.ts`
|
|
10
10
|
- Depends on: comms-abstraction Phase 1
|
|
11
11
|
- Acceptance: mocked-client tests cover both sender configs
|
|
12
|
-
- [ ] **Task 1.2**: E.164 validation + error
|
|
13
|
-
- Description: `libphonenumber-js` normalization; Twilio error codes into `
|
|
12
|
+
- [ ] **Task 1.2**: E.164 validation + error classification
|
|
13
|
+
- Description: `libphonenumber-js` normalization; Twilio error-code → `errorCode`/`errorClass` map per the IP table (unknown codes → `transient`); full error payload into `CommsMessage.metadata`; Twilio SDK calls wrapped with `withApiErrorHandling`
|
|
14
14
|
- Files: `comms/src/adapters/twilioSms.ts`
|
|
15
15
|
- Depends on: 1.1
|
|
16
|
-
- Acceptance: invalid number → 400 before API call;
|
|
17
|
-
- [ ] **Task 1.3**:
|
|
16
|
+
- Acceptance: invalid number → 400 before API call; fixtures for at least one code per class (e.g. 21610 permanent, 20429 transient, 20003 config) assert `errorClass`; permanent failures skip the inline retry
|
|
17
|
+
- [ ] **Task 1.3**: Dashboard metadata + hooks coverage
|
|
18
|
+
- Description: `metadata.consoleUrl` deep link per message SID; `onError` fires with the classified `SendResult`
|
|
19
|
+
- Files: `comms/src/adapters/twilioSms.ts` + tests
|
|
20
|
+
- Depends on: 1.2
|
|
21
|
+
- Acceptance: failed-send test asserts consoleUrl and onError invocation
|
|
22
|
+
- [ ] **Task 1.4**: Peer dep + example-backend registration + docs
|
|
18
23
|
- Description: optional peer `twilio`; env-gated registration; reference + env-var docs
|
|
19
24
|
- Files: `comms/package.json`, `example-backend/src/server.ts`, `docs/reference/comms.md`, `docs/reference/environment-variables.md`
|
|
20
25
|
- Depends on: 1.1
|
|
21
26
|
- Acceptance: compile + boot without twilio installed when unconfigured
|
|
22
27
|
|
|
23
|
-
## Phase 2 — Delivery callbacks (gated on inbound-webhooks)
|
|
28
|
+
## Phase 2 — Delivery callbacks + opt-outs (gated on inbound-webhooks)
|
|
24
29
|
|
|
25
30
|
- [ ] **Task 2.1**: Status callback route
|
|
26
|
-
- Description: webhook endpoint with Twilio signature verification via inbound-webhooks framework
|
|
31
|
+
- Description: webhook endpoint with Twilio signature verification via inbound-webhooks framework; status mapping per IP table incl. `ErrorCode` propagation
|
|
27
32
|
- Files: `comms/src/adapters/twilioSms.ts`, webhook registration
|
|
28
33
|
- Depends on: inbound-webhooks IP
|
|
29
|
-
- Acceptance: signed payload updates `CommsMessage.status
|
|
34
|
+
- Acceptance: signed payload updates `CommsMessage.status` (+ `errorCode` on failure); unsigned rejected 401
|
|
35
|
+
- [ ] **Task 2.2**: STOP/START opt-out handling
|
|
36
|
+
- Description: inbound keyword webhook → `OptOutEvent` → consumer `onOptOut`; opt-in (START) emitted symmetrically
|
|
37
|
+
- Files: `comms/src/adapters/twilioSms.ts`, webhook registration + tests
|
|
38
|
+
- Depends on: 2.1
|
|
39
|
+
- Acceptance: STOP fixture fires `onOptOut` with `reason: "sms-stop"`; 21610 on later sends classified `permanent`
|
|
@@ -7,11 +7,11 @@ IP: [comms-adapter-twilio-verify](../implementationPlans/comms-adapter-twilio-ve
|
|
|
7
7
|
- Files: `comms/src/adapters/twilioVerify.ts`
|
|
8
8
|
- Depends on: comms-abstraction Phase 1
|
|
9
9
|
- Acceptance: mocked-client tests for approved/pending/expired/max-attempts
|
|
10
|
-
- [ ] **Task 2**: Redacted logging
|
|
11
|
-
- Description: `CommsMessage` rows with channel `verification`,
|
|
10
|
+
- [ ] **Task 2**: Redacted logging + error classification
|
|
11
|
+
- Description: `CommsMessage` rows with channel `verification`, fully redacted destination, no codes, and verification channel metadata on start; `errorCode`/`errorClass` mapping (rate-limit transient, expired/max-attempts permanent, bad SID config); rows flagged non-retryable; `onError` fires on failures
|
|
12
12
|
- Files: `comms/src/adapters/twilioVerify.ts`
|
|
13
13
|
- Depends on: Task 1
|
|
14
|
-
- Acceptance: log assertion tests prove no code/full destination in any row
|
|
14
|
+
- Acceptance: log assertion tests prove no code/full destination in any row; failure fixtures assert class + onError
|
|
15
15
|
- [ ] **Task 3**: Registration + docs
|
|
16
16
|
- Description: env-gated example-backend registration; fail-fast on missing service SID; reference + env docs
|
|
17
17
|
- Files: `example-backend/src/server.ts`, `docs/reference/comms.md`, `docs/reference/environment-variables.md`
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Tasks: Comms admin dashboard (errors, retries, log digging)
|
|
2
|
+
|
|
3
|
+
IP: [comms-admin-dashboard](../implementationPlans/comms-admin-dashboard.md)
|
|
4
|
+
|
|
5
|
+
## Phase 1 — Backend routes
|
|
6
|
+
|
|
7
|
+
- [ ] **Task 1.1**: Upgrade explorer to `commsDashboard.ts` list + detail
|
|
8
|
+
- Description: rich filters (channel/provider/status/errorClass/errorCode/userId/to/templateId/dates/`q`), pagination, `GET /comms/messages/:id` with attempts + metadata + retained payload
|
|
9
|
+
- Files: `comms/src/routes/commsDashboard.ts` + supertest
|
|
10
|
+
- Depends on: comms-abstraction Phase 2 (incl. hooks/error-taxonomy additions)
|
|
11
|
+
- Acceptance: every filter covered by a supertest case; non-admin 403
|
|
12
|
+
- [ ] **Task 1.2**: `retryMessage` facade + retry route
|
|
13
|
+
- Description: retryability validation (status, errorClass, payload retention, channel configured, not verification), linked rows via `retriedFromId`/`retriedById`, hooks fire with `isRetry: true`, acting admin recorded
|
|
14
|
+
- Files: `comms/src/commsService.ts`, `comms/src/routes/commsDashboard.ts` + tests
|
|
15
|
+
- Depends on: 1.1
|
|
16
|
+
- Acceptance: each non-retryable reason returns 400 with its stable `code`; successful retry creates a linked row
|
|
17
|
+
- [ ] **Task 1.3**: `retryMany` + `/comms/stats`
|
|
18
|
+
- Description: bulk retry with cap + skipped reasons; aggregation by channel × provider × status with day buckets and failure rate
|
|
19
|
+
- Files: `comms/src/routes/commsDashboard.ts` + tests
|
|
20
|
+
- Depends on: 1.2
|
|
21
|
+
- Acceptance: stats counts match list totals for the same filter/range; cap enforced
|
|
22
|
+
|
|
23
|
+
## Phase 2 — Admin screens
|
|
24
|
+
|
|
25
|
+
- [ ] **Task 2.1**: `CommsDashboardScreen`
|
|
26
|
+
- Description: stats cards, filter bar (URL-persisted), DataTable with status badges + inline retry
|
|
27
|
+
- Files: `admin-frontend/src/comms/CommsDashboardScreen.tsx`, `CommsStatusBadge.tsx`, `useCommsDashboardApi.tsx` + tests
|
|
28
|
+
- Depends on: 1.1, 1.3
|
|
29
|
+
- Acceptance: loading/error/empty states; filters round-trip through the URL
|
|
30
|
+
- [ ] **Task 2.2**: `CommsMessageDetail`
|
|
31
|
+
- Description: attempt timeline, provider console links, JSON viewer for payload/metadata, confirmed retry button with disabled-reason tooltips
|
|
32
|
+
- Files: `admin-frontend/src/comms/CommsMessageDetail.tsx` + tests
|
|
33
|
+
- Depends on: 1.2, 2.1
|
|
34
|
+
- Acceptance: non-retryable rows show the specific reason; retry navigates to the new row
|
|
35
|
+
- [ ] **Task 2.3**: Example app + admin-spa wiring
|
|
36
|
+
- Description: expo-router screens under `app/admin/comms/`, admin-spa nav entry, `bun run sdk`
|
|
37
|
+
- Files: `example-frontend/app/admin/comms/*`, `example-frontend/store/openApiSdk.ts`, admin-spa nav
|
|
38
|
+
- Depends on: 2.1, 2.2
|
|
39
|
+
- Acceptance: frontend verification in the running example app with screenshots on the PR
|
|
40
|
+
|
|
41
|
+
## Phase 3 — Bulk retry UI + docs
|
|
42
|
+
|
|
43
|
+
- [ ] **Task 3.1**: "Retry all failed" flow
|
|
44
|
+
- Description: filtered bulk retry with count confirmation modal; skipped-reason summary toast
|
|
45
|
+
- Files: `admin-frontend/src/comms/CommsDashboardScreen.tsx` + tests
|
|
46
|
+
- Depends on: 1.3, 2.1
|
|
47
|
+
- Acceptance: confirmation shows the exact count; result summarizes retried/skipped
|
|
48
|
+
- [ ] **Task 3.2**: Docs + rules
|
|
49
|
+
- Description: dashboard section in comms reference, admin reference update, rulesync
|
|
50
|
+
- Files: `docs/reference/comms.md`, `docs/reference/admin.md`, `.rulesync/**`
|
|
51
|
+
- Depends on: 2.x
|
|
52
|
+
- Acceptance: `bun run rules:check` passes
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# Task List: Migrate CI/CD to CircleCI
|
|
2
|
+
|
|
3
|
+
See: [`docs/implementationPlans/migrate-cicd-to-circleci.md`](../implementationPlans/migrate-cicd-to-circleci.md)
|
|
4
|
+
Research: [`docs/implementationPlans/migrate-cicd-to-circleci-research.md`](../implementationPlans/migrate-cicd-to-circleci-research.md)
|
|
5
|
+
|
|
6
|
+
## Instructions for the implementing agent
|
|
7
|
+
|
|
8
|
+
- Dual-run every phase: CircleCI green → flip required checks → delete GHA twin. Never enable tag publish on both systems.
|
|
9
|
+
- Do not store plaintext GCP JSON keys in CircleCI if OIDC is available; migrate `preview-cleanup` off `GCP_SA_KEY`.
|
|
10
|
+
- Pin orb versions (including `circleci/node` with Bun support ≥7.2.0).
|
|
11
|
+
- Prefer path parameters that mirror existing GHA path filters.
|
|
12
|
+
- Update docs in the same PR that changes the source of truth for how CI runs.
|
|
13
|
+
- After Phase 0, confirm CircleCI project follows the GitHub default branch `master`.
|
|
14
|
+
|
|
15
|
+
## Phase 0: Prerequisites
|
|
16
|
+
|
|
17
|
+
- [ ] **Task 0.1**: Confirm CircleCI org/plan and project link
|
|
18
|
+
- Description: Verify the requester-created CircleCI organization, plan, and that `FlourishHealth/terreno` is connected with permission to report GitHub checks. Enable **dynamic config** / setup workflows for the project. Record org slug + project slug in the IP header or how-to doc.
|
|
19
|
+
- Files: `docs/how-to/circleci.md` (stub OK)
|
|
20
|
+
- Depends on: none (human prerequisite)
|
|
21
|
+
- Acceptance: a manual “hello” pipeline can be triggered from the project; dynamic config is enabled.
|
|
22
|
+
|
|
23
|
+
- [ ] **Task 0.2**: Create CircleCI Contexts (empty shells)
|
|
24
|
+
- Description: Create contexts named in the IP (`terreno-npm`, `terreno-netlify`, `terreno-expo`, `terreno-gcp`, `terreno-e2e`, `terreno-release`, `terreno-agentic`, `terreno-github-api`). Document which GitHub secrets map into each. Do not paste secret values into the repo.
|
|
25
|
+
- Files: `docs/how-to/circleci.md`
|
|
26
|
+
- Depends on: Task 0.1
|
|
27
|
+
- Acceptance: contexts exist; mapping table is complete; access restrictions noted for `terreno-release`.
|
|
28
|
+
|
|
29
|
+
- [ ] **Task 0.3**: Inventory required GitHub checks
|
|
30
|
+
- Description: List current branch-protection required checks and map each to the GHA job `name:` and the future CircleCI job name. Start from `docs/explanation/repository-settings.md` and live settings.
|
|
31
|
+
- Files: `docs/how-to/circleci.md` or a short table in the IP
|
|
32
|
+
- Depends on: none
|
|
33
|
+
- Acceptance: table covers policies, rulesync, package CI, fingerprint, and CD-related checks.
|
|
34
|
+
|
|
35
|
+
## Phase 1: Foundation
|
|
36
|
+
|
|
37
|
+
- [ ] **Task 1.1**: Add setup + continue config skeleton
|
|
38
|
+
- Description: Create `.circleci/config.yml` with `setup: true` using `circleci/path-filtering` (and `circleci/continuation`). Create `.circleci/continue-config.yml` with parameters for each package/area and a no-op `config-ok` job that always runs.
|
|
39
|
+
- Files: `.circleci/config.yml`, `.circleci/continue-config.yml`
|
|
40
|
+
- Depends on: Task 0.1
|
|
41
|
+
- Acceptance: push triggers setup → continuation; `config-ok` is green.
|
|
42
|
+
|
|
43
|
+
- [ ] **Task 1.2**: Shared Bun + cache commands
|
|
44
|
+
- Description: Add reusable commands (inline or orb) for installing Bun via `circleci/node`, `bun install --frozen-lockfile`, and cache keys equivalent to today’s GHA bun cache. Pin Bun policy (`latest` vs pin) consistently with EAS jobs that need a pin.
|
|
45
|
+
- Files: `.circleci/continue-config.yml`
|
|
46
|
+
- Depends on: Task 1.1
|
|
47
|
+
- Acceptance: a sample job restores cache on second run; install is frozen-lockfile.
|
|
48
|
+
|
|
49
|
+
- [ ] **Task 1.3**: Path-filter mapping
|
|
50
|
+
- Description: Encode path → parameter mapping for api, ai, ui, rtk, comms, mcp-server, admin-*, example-*, demo, docs/website, terraform, e2e-relevant sets, matching current workflow path filters.
|
|
51
|
+
- Files: `.circleci/config.yml`
|
|
52
|
+
- Depends on: Task 1.1
|
|
53
|
+
- Acceptance: a docs-only change sets docs/deploy params without setting `run-api`.
|
|
54
|
+
|
|
55
|
+
## Phase 2: Package CI + policy
|
|
56
|
+
|
|
57
|
+
- [ ] **Task 2.1**: Port package CI jobs
|
|
58
|
+
- Description: Port api/ai/rtk/ui/ui-demo/comms/mcp-server/example-frontend/example-backend(+script)/admin-spa CI to CircleCI jobs gated by path params. Include Mongo service where GHA used it. Fix mcp branch filter to `master`.
|
|
59
|
+
- Files: `.circleci/continue-config.yml`, possibly package scripts unchanged
|
|
60
|
+
- Depends on: Task 1.2, Task 1.3
|
|
61
|
+
- Acceptance: dual-run green for each package on a change that touches it; GHA still required.
|
|
62
|
+
|
|
63
|
+
- [ ] **Task 2.2**: Port Docker build-only job
|
|
64
|
+
- Description: Port `example-backend-docker.yml` to CircleCI remote Docker / machine with layer caching replacement for `type=gha`.
|
|
65
|
+
- Files: `.circleci/continue-config.yml`
|
|
66
|
+
- Depends on: Task 2.1
|
|
67
|
+
- Acceptance: PR touching `example-backend/**` builds the image without pushing.
|
|
68
|
+
|
|
69
|
+
- [ ] **Task 2.3**: Port repo-policies + rulesync + DCO
|
|
70
|
+
- Description: Port `repo-policies.yml`, `rulesync-check.yml`, and fork DCO checks. DCO must use GitHub API via `terreno-github-api` context.
|
|
71
|
+
- Files: `.circleci/continue-config.yml`
|
|
72
|
+
- Depends on: Task 0.2, Task 1.2
|
|
73
|
+
- Acceptance: intentional barrel-import / dirty rulesync / missing DCO on a fork PR fails the CircleCI job.
|
|
74
|
+
|
|
75
|
+
- [ ] **Task 2.4**: Dual-run cutover for Phase 2
|
|
76
|
+
- Description: Add CircleCI checks to branch protection; remove GHA package/policy workflows once trusted; delete corresponding `.github/workflows/*-ci.yml` and policy workflows.
|
|
77
|
+
- Files: `.github/workflows/*`, `docs/explanation/repository-settings.md`
|
|
78
|
+
- Depends on: Task 2.1, Task 2.2, Task 2.3
|
|
79
|
+
- Acceptance: required checks are CircleCI-only for these surfaces; GHA files gone.
|
|
80
|
+
|
|
81
|
+
## Phase 3: Playwright E2E
|
|
82
|
+
|
|
83
|
+
- [ ] **Task 3.1**: Port `e2e-ci` and `admin-spa-integration`
|
|
84
|
+
- Description: Mongo replica set, E2E secrets context, Playwright browsers, artifact store for reports. Skip Dependabot-equivalent if applicable.
|
|
85
|
+
- Files: `.circleci/continue-config.yml`
|
|
86
|
+
- Depends on: Task 2.1, Task 0.2
|
|
87
|
+
- Acceptance: matrix (or equivalent) passes on master; artifacts downloadable.
|
|
88
|
+
|
|
89
|
+
- [ ] **Task 3.2**: Dual-run cutover for E2E
|
|
90
|
+
- Description: Flip required checks if any; delete GHA e2e/admin-spa-integration workflows.
|
|
91
|
+
- Files: `.github/workflows/e2e-ci.yml`, `admin-spa-integration.yml`, `admin-spa-ci.yml` as applicable
|
|
92
|
+
- Depends on: Task 3.1
|
|
93
|
+
- Acceptance: GHA twins deleted; CircleCI owns e2e.
|
|
94
|
+
|
|
95
|
+
## Phase 4: Netlify deploys
|
|
96
|
+
|
|
97
|
+
- [ ] **Task 4.1**: Port demo / frontend-example / docs Netlify workflows
|
|
98
|
+
- Description: Build + `netlify-cli` deploy prod/preview; preserve alias naming (`pr-N`); recreate GitHub Deployment statuses via API if still desired.
|
|
99
|
+
- Files: `.circleci/continue-config.yml`
|
|
100
|
+
- Depends on: Task 0.2, Task 1.3
|
|
101
|
+
- Acceptance: preview deploy URL posted or visible; prod deploy on master path filter.
|
|
102
|
+
|
|
103
|
+
- [ ] **Task 4.2**: Preview cleanup port
|
|
104
|
+
- Description: On PR close, clean Netlify/GCP preview resources from CircleCI (webhook or GitHub App → pipeline). Prefer OIDC over `GCP_SA_KEY`.
|
|
105
|
+
- Files: `.circleci/continue-config.yml`
|
|
106
|
+
- Depends on: Task 4.1
|
|
107
|
+
- Acceptance: closing a PR removes preview resources; no orphaned Cloud Run `pr-N` services in a test PR.
|
|
108
|
+
|
|
109
|
+
- [ ] **Task 4.3**: Dual-run cutover for Netlify
|
|
110
|
+
- Description: Delete GHA deploy workflows after CircleCI trusted.
|
|
111
|
+
- Files: `.github/workflows/demo-deploy.yml`, `frontend-example-deploy.yml`, `docs-deploy.yml`, `preview-cleanup.yml`
|
|
112
|
+
- Depends on: Task 4.1, Task 4.2
|
|
113
|
+
- Acceptance: GHA deploy twins deleted.
|
|
114
|
+
|
|
115
|
+
## Phase 5: EAS + fingerprint
|
|
116
|
+
|
|
117
|
+
- [ ] **Task 5.1**: Relocate CI scripts
|
|
118
|
+
- Description: Move EAS/fingerprint shell scripts from `.github/workflows/scripts/` to `scripts/ci/` (or `.circleci/scripts/`) and update callers.
|
|
119
|
+
- Files: `scripts/ci/*`, old script paths
|
|
120
|
+
- Depends on: none
|
|
121
|
+
- Acceptance: scripts runnable locally with documented env; no broken references.
|
|
122
|
+
|
|
123
|
+
- [ ] **Task 5.2**: Port eas-pr, eas-dev-build, fingerprint-gate
|
|
124
|
+
- Description: CircleCI jobs using `EXPO_TOKEN`; PR comments and label gate via GitHub API; manual pipeline for eas-dev-build.
|
|
125
|
+
- Files: `.circleci/continue-config.yml`
|
|
126
|
+
- Depends on: Task 5.1, Task 0.2
|
|
127
|
+
- Acceptance: fingerprint change fails until `fingerprint-acknowledged`; EAS update/build path works on a test PR.
|
|
128
|
+
|
|
129
|
+
- [ ] **Task 5.3**: Dual-run cutover for EAS
|
|
130
|
+
- Description: Delete GHA eas/fingerprint workflows after trust.
|
|
131
|
+
- Files: `.github/workflows/eas-pr.yml`, `eas-dev-build.yml`, `fingerprint-gate.yml`
|
|
132
|
+
- Depends on: Task 5.2
|
|
133
|
+
- Acceptance: GHA twins deleted; CircleCI checks required where fingerprint was required.
|
|
134
|
+
|
|
135
|
+
## Phase 6: GCP CD + OIDC
|
|
136
|
+
|
|
137
|
+
- [ ] **Task 6.1**: Add CircleCI OIDC provider in terraform
|
|
138
|
+
- Description: Extend or add module so GCP trusts CircleCI OIDC alongside GitHub during dual-run. Wire terreno terraform root; document outputs for CircleCI project settings.
|
|
139
|
+
- Files: `terraform/modules/**`, terreno/Flourish terraform roots, `terraform/README.md`
|
|
140
|
+
- Depends on: Task 0.1
|
|
141
|
+
- Acceptance: `gcloud` auth from a CircleCI job succeeds with WIF (no JSON key).
|
|
142
|
+
|
|
143
|
+
- [ ] **Task 6.2**: Port `cd.yml`
|
|
144
|
+
- Description: Path-filtered terraform fmt/preview/apply + Docker build/push + Cloud Run deploys + mcp-test/deploy. Preserve concurrency semantics (do not cancel in-flight prod applies).
|
|
145
|
+
- Files: `.circleci/continue-config.yml`
|
|
146
|
+
- Depends on: Task 6.1
|
|
147
|
+
- Acceptance: terraform preview on PR; apply+deploy on master for a safe test path; GitHub Deployment records optional but documented.
|
|
148
|
+
|
|
149
|
+
- [ ] **Task 6.3**: Dual-run cutover for CD
|
|
150
|
+
- Description: Single deployer: disable GHA `cd.yml` when CircleCI CD is required; remove GitHub OIDC provider only after GHA CD is gone (or keep read-only if other repos need it — document).
|
|
151
|
+
- Files: `.github/workflows/cd.yml`, terraform OIDC
|
|
152
|
+
- Depends on: Task 6.2
|
|
153
|
+
- Acceptance: only CircleCI performs terreno CD; no double apply.
|
|
154
|
+
|
|
155
|
+
## Phase 7: npm publish
|
|
156
|
+
|
|
157
|
+
- [ ] **Task 7.1**: Port publish-on-tag + manual feature-flags publish
|
|
158
|
+
- Description: Reproduce package publish graph, upgrade-docs gate, version bump, Zoom notify, demo dispatch, docs version cut. Use `terreno-release` + `terreno-npm` contexts.
|
|
159
|
+
- Files: `.circleci/continue-config.yml`
|
|
160
|
+
- Depends on: Task 0.2, Task 2.1
|
|
161
|
+
- Acceptance: dry-run or package-by-package rehearsal documented; Zoom path tested against a sandbox webhook if available.
|
|
162
|
+
|
|
163
|
+
- [ ] **Task 7.2**: Single-writer tag cutover
|
|
164
|
+
- Description: In one coordinated change: enable CircleCI tag pipeline; delete/disable `.github/workflows/publish-on-tag.yml` and manual GHA publish; verify no double publish.
|
|
165
|
+
- Files: `.github/workflows/publish-on-tag.yml`, `publish-feature-flags-manual.yml`
|
|
166
|
+
- Depends on: Task 7.1
|
|
167
|
+
- Acceptance: next tag publishes once from CircleCI only.
|
|
168
|
+
|
|
169
|
+
## Phase 8: Mobile (post-v1, required for CC1)
|
|
170
|
+
|
|
171
|
+
- [ ] **Task 8.1**: Port Maestro + Appium Android
|
|
172
|
+
- Description: Port `maestro-e2e` and Android half of `demo-appium-ci` to CircleCI Linux VM with emulator strategy documented.
|
|
173
|
+
- Files: `.circleci/continue-config.yml`
|
|
174
|
+
- Depends on: Task 5.2
|
|
175
|
+
- Acceptance: manual pipeline runs Android Appium and Maestro successfully.
|
|
176
|
+
|
|
177
|
+
- [ ] **Task 8.2**: Port Appium iOS on CircleCI macOS
|
|
178
|
+
- Description: Select macOS resource class/image with Working WDA; port iOS job; compare flake rate to GHA `macos-15`.
|
|
179
|
+
- Files: `.circleci/continue-config.yml`
|
|
180
|
+
- Depends on: Task 8.1
|
|
181
|
+
- Acceptance: iOS Appium green on a representative run; then delete GHA Appium workflow.
|
|
182
|
+
|
|
183
|
+
## Phase 9: GitHub-native + agentic replacements
|
|
184
|
+
|
|
185
|
+
- [ ] **Task 9.1**: Replace CodeQL workflow
|
|
186
|
+
- Description: Implement SARIF upload to GitHub Code Scanning from CircleCI or an approved SAST substitute; delete `codeql-analysis.yml` only when coverage is accepted.
|
|
187
|
+
- Files: `.circleci/continue-config.yml`, `.github/workflows/codeql-analysis.yml`
|
|
188
|
+
- Depends on: Task 0.2
|
|
189
|
+
- Acceptance: Security tab still receives results **or** explicit maintainer sign-off on alternative.
|
|
190
|
+
|
|
191
|
+
- [ ] **Task 9.2**: Replace Dependabot auto-merge + triage + roadmap-generate + docs-audit
|
|
192
|
+
- Description: Implement CircleCI (or Renovate) equivalents; wire issue/schedule triggers without leaving required logic on GHA.
|
|
193
|
+
- Files: `.circleci/continue-config.yml`, corresponding GHA deletions
|
|
194
|
+
- Depends on: Task 0.2
|
|
195
|
+
- Acceptance: each former workflow’s acceptance behavior has an owner on CircleCI; GHA files deleted.
|
|
196
|
+
|
|
197
|
+
- [ ] **Task 9.3**: Replace architectural review + gh-aw agentics
|
|
198
|
+
- Description: Per lockfile (`update-rules`, `update-docs`, daily improvers) and `architectural-pr-review` / `agentics-maintenance`: either port to CircleCI scheduled/PR pipelines with the same scripts or **retire** with maintainer sign-off. CC1 forbids leaving them on GHA.
|
|
199
|
+
- Files: `.github/workflows/*lock*`, `architectural-pr-review.yml`, `agentics-maintenance.yml`, `.circleci/continue-config.yml`
|
|
200
|
+
- Depends on: Task 0.2
|
|
201
|
+
- Acceptance: written retire-or-port decision for each; no gh-aw workflows remain if ported/retired.
|
|
202
|
+
|
|
203
|
+
## Phase 10: Cleanup
|
|
204
|
+
|
|
205
|
+
- [ ] **Task 10.1**: Docs sweep
|
|
206
|
+
- Description: Update CONTRIBUTING, repository-settings, terraform README, deploy guides, AGENTS/Cursor Cloud CI notes to CircleCI-first. Remove stale GHA instructions.
|
|
207
|
+
- Files: `docs/**`, `CONTRIBUTING.md`, `AGENTS.md` / rules as needed
|
|
208
|
+
- Depends on: Phases 2–7 at minimum; 8–9 for full CC1
|
|
209
|
+
- Acceptance: `rg -n "GitHub Actions" docs/explanation/repository-settings.md` and deploy docs reflect CircleCI as source of truth.
|
|
210
|
+
|
|
211
|
+
- [ ] **Task 10.2**: Final GHA workflow purge + IP close
|
|
212
|
+
- Description: Ensure `.github/workflows` has no CI/CD yml left (except intentionally empty dir or README). Update `PLAN_INDEX.md`; archive IP when Complete.
|
|
213
|
+
- Files: `.github/workflows/`, `docs/implementationPlans/PLAN_INDEX.md`
|
|
214
|
+
- Depends on: Task 9.3, Task 10.1, Task 8.2
|
|
215
|
+
- Acceptance: `ls .github/workflows/*.yml` is empty (or only an agreed stub); IP status Complete.
|