Skip to content

Commit 019861e

Browse files
Merge pull request #46 from engineeredsoftware/v31/gate-3-profile-account-state
V31 Gate 3: Profile Account State
2 parents e607b44 + a7eb3c4 commit 019861e

24 files changed

Lines changed: 1042 additions & 38 deletions

.github/workflows/bitcode-gate-quality.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ jobs:
9797
node scripts/check-v30-gate10-promotion-readiness.mjs --promotion-mode --skip-branch-check
9898
node scripts/check-v31-gate1-spec-roadmap-opening.mjs --skip-branch-check
9999
node scripts/check-v31-gate2-auxillaries-package-route-contracts.mjs --skip-branch-check
100+
node scripts/check-v31-gate3-profile-account-state.mjs --skip-branch-check
100101
else
101102
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
102103
exit 1
@@ -137,6 +138,7 @@ jobs:
137138
run: |
138139
pnpm --dir uapi exec jest --runTestsByPath \
139140
tests/userDataRoute.test.ts \
141+
tests/profileStep.test.tsx \
140142
tests/api/readReviewRoute.test.ts \
141143
tests/api/pipelineHarnessRoute.test.ts \
142144
tests/terminalPipelineHarnessClient.test.ts \

BITCODE_SPEC_V31.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,11 @@ Gate 2 contract precision:
231231
Gate 3 profile/account precision:
232232

233233
- Profile state binds user id, display identity, account readiness, wallet binding, model preference, template preference, notification posture, data-sharing posture, and completeness root.
234-
- Incomplete profile state must name blockers and repair routes rather than rendering as generic missing data.
234+
- Account identity is a typed support object containing user id, handle, display name, email, email verification, company, and role; it is not inferred again in UI surfaces.
235+
- Incomplete profile state must name completeness issues, blocking issue ids, repair routes, repair panes, and retry posture rather than rendering as generic missing data.
236+
- Model and template preferences are support readiness posture, with deterministic preference roots and repair actions when missing.
237+
- Notification posture names contact readiness, unread count, latest notification time, and source-safety class without exposing message bodies in the profile readiness summary.
238+
- Data-sharing posture names repository counts and enabled/disabled repository counts without exposing protected source.
235239
- Wallet binding is a capability/readiness field, not a private-key or custody claim.
236240

237241
Gate 4 Connects precision:

BITCODE_SPEC_V31_DELTA.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ Closure acceptance:
110110
- incomplete profile/account state names blockers and recovery routes;
111111
- focused package, route, and pane tests prove persistence, hydration, projection, and source-safety.
112112

113+
Gate 3 implementation centers:
114+
115+
- `AuxillariesProfileState` carries `accountIdentity`, `profileCompleteness.issues`, `profileCompleteness.repairRoutes`, `walletBinding`, `preferences`, `notificationPosture`, and `dataSharingPosture` as package-owned source-safe state.
116+
- `/api/auxillaries/data` hydrates profile, GitHub connection, wallet status, BTD holdings, model preferences, template preferences, recent notifications, and repository inventory before delegating the read model to `buildAuxillaryDataPayload`.
117+
- The Profile pane consumes `profileState` instead of locally deriving readiness, rendering account readiness, wallet, notification, data-sharing, and repair actions from the package contract.
118+
- Focused tests prove account hydration, route projection, unread-notification posture, template preference posture, repair routes, and JSON-safe contract roots.
119+
113120
### Gate 4: Connects Provider Readiness And Recovery
114121

115122
Gate 4 deepens provider connection readiness.

BITCODE_SPEC_V31_NOTES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,10 @@ Gate 1 is closed only when the V31 draft family validates over V30, the roadmap
8080
Gate 2 is closed only when Auxillaries support-state contracts are package-owned and JSON-safe.
8181
Routes may still authenticate, read/write explicit storage rows, and return framework responses, but readiness and policy objects for Profile, Connects, Interfaces, Wallet, BTD, organization, diagnostics, and recovery must be built through `packages/api/src/routes/auxillaries-contract.ts`.
8282
The route payload can preserve existing UI fields for compatibility, but provider tokens, wallet secrets, service keys, database credentials, private prompts, and protected source must be redacted before any UI, telemetry, or proof-hook consumption.
83+
84+
## Gate 3 closure note
85+
86+
Gate 3 is closed only when Profile/account state is not just a form payload.
87+
It must be a package-owned support state that binds account identity, profile completeness issues, repair routes, wallet binding posture, model/template preference posture, notification posture, data-sharing posture, and proof roots.
88+
The Profile pane may present and link repairs, but it must consume the package contract and must not locally rederive account readiness or completeness law.
89+
Route hydration must include template preference and notification readback where available, while missing storage rows degrade into explicit repair posture rather than generic missing data.

BITCODE_SPEC_V31_PARITY_MATRIX.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ No `_legacy/` source is active source truth.
5757
| --- | --- | --- | --- | --- |
5858
| Draft family and branch posture | Gate 1 | `BITCODE_SPEC_V31.md`, DELTA, NOTES, PARITY, `BITCODE_SPEC.txt`, branch `v31/gate-1-spec-roadmap-opening` | drafted | V31 family validates in draft mode over active V30 and `check:v31-gate1` passes. |
5959
| Roadmap truth | Gate 1 | `SPECIFICATIONS_ROADMAP.md`, README, PR template, workflow posture | drafted | Roadmap states V30 active, V31 draft, and coherent V32-V37 responsibilities. |
60-
| Auxillaries package and route contracts | Gate 2 | `packages/api`, `packages/orm`, `packages/btd`, `uapi/app/auxillaries`, route tests | pending | Shared Profile, Connects, Interfaces, Wallet, BTD, organization, readiness, and recovery objects are package-owned and JSON-safe. |
61-
| Profile and account state | Gate 3 | Profile/account packages, routes, Auxillaries pane tests | pending | Profile, account identity, wallet binding, preferences, notification posture, and completeness blockers are typed and recoverable. |
60+
| Auxillaries package and route contracts | Gate 2 | `packages/api/src/routes/auxillaries-contract.ts`, `packages/api/src/routes/auxillaries.ts`, package docs, route tests | drafted | Shared Profile, Connects, Interfaces, Wallet, BTD, organization, readiness, and recovery objects are package-owned and JSON-safe. |
61+
| Profile and account state | Gate 3 | `packages/api/src/routes/auxillaries-contract.ts`, `packages/api/src/routes/auxillaries.ts`, `uapi/app/auxillaries/components/AuxillariesProfilePane.tsx`, route/pane tests | drafted | Profile, account identity, wallet binding, preferences, notification posture, and completeness blockers are typed and recoverable. |
6262
| Connects provider readiness and recovery | Gate 4 | Provider packages, connection routes, readiness/recovery tests | pending | Provider readiness names credential posture without secrets, scopes class, readback status, blocker, repair action, and before/after roots. |
6363
| Wallet and BTD pane readiness | Gate 5 | `packages/btd`, Wallet/BTD panes, settlement/read-right tests | pending | Wallet and BTD panes consume V30 no-custody, signer, read-right, treasury, and settlement-readiness primitives. |
6464
| Organization team role policy authority | Gate 6 | Organization packages/routes, policy authority tests, Terminal/Auxillaries projections | pending | Organization, team, role, grants, multi-sig readiness, policy decisions, denials, and recovery routes are typed and fail closed. |
@@ -105,9 +105,9 @@ No `_legacy/` source is active source truth.
105105

106106
| Requirement | Source evidence | Current V31 judgment |
107107
| --- | --- | --- |
108-
| Profile/account state is typed | Profile/account package objects and tests | pending |
109-
| Wallet binding and preferences are recoverable support state | profile/account routes and Auxillaries pane readback | pending |
110-
| Incomplete state names blockers and repair routes | component tests and route tests | pending |
108+
| Profile/account state is typed | `AuxillariesAccountIdentity`, `AuxillariesProfileCompletenessIssue`, `AuxillariesPreferencePosture`, `AuxillariesNotificationPosture`, and `AuxillariesDataSharingPosture` in `packages/api/src/routes/auxillaries-contract.ts` | drafted |
109+
| Wallet binding and preferences are recoverable support state | `buildAuxillariesProfileState` emits wallet, model, and template repair issues; `/api/auxillaries/data` hydrates model and template preferences before `buildAuxillaryDataPayload` | drafted |
110+
| Incomplete state names blockers and repair routes | `packages/api/src/routes/__tests__/auxillaries-contract.test.ts`, `uapi/tests/userDataRoute.test.ts`, and `uapi/tests/profileStep.test.tsx` cover issues, blockers, repair routes, and Profile pane projection | drafted |
111111

112112
## Gate 4 Parity
113113

SPECIFICATIONS_ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
- Current active canonical pointer: `BITCODE_SPEC.txt` -> `V30`
66
- Current active canon: `BITCODE_SPEC_V30.md`
77
- Current draft target: `BITCODE_SPEC_V31.md`
8-
- Current working gate: V31 Gate 2 Auxillaries package and route contracts, which makes Profile, Connects, Interfaces, Wallet, BTD, organization, readiness, and recovery support-state objects package-owned, JSON-safe, and route-consumable over the V30 Protocol/BTD substrate.
8+
- Current working gate: V31 Gate 3 Profile and account state, which deepens the package-owned Auxillaries Profile contract with account identity, wallet binding posture, model/template preferences, notifications, data-sharing posture, explicit blockers, and repair routes over the V30 Protocol/BTD substrate.
99
- Purpose: concise running index of Bitcode/ENGI specification history, current work, and planned work.
1010

1111
This roadmap is not an active system specification.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"check:v30-gate10": "node scripts/check-v30-gate10-promotion-readiness.mjs",
6767
"check:v31-gate1": "node scripts/check-v31-gate1-spec-roadmap-opening.mjs",
6868
"check:v31-gate2": "node scripts/check-v31-gate2-auxillaries-package-route-contracts.mjs",
69+
"check:v31-gate3": "node scripts/check-v31-gate3-profile-account-state.mjs",
6970
"check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic",
7071
"check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title",
7172
"check:spec-quality:v24": "node scripts/run-bitcode-spec-quality.mjs --mode strict-version --version V24",

packages/api/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ objects must be built through `buildAuxillariesContractSnapshot` and
2727
secrets, private prompts, protected source, service keys, and database
2828
credentials before UI, telemetry, or proof-hook consumption.
2929

30+
Profile/account state is also package-owned. `AuxillariesProfileState` binds
31+
the support identity, completeness issues, repair routes, wallet binding,
32+
model/template preferences, notification posture, data-sharing posture, and
33+
proof roots. Profile UI and routes can display or persist explicit fields, but
34+
they should not recalculate readiness locally; missing profile/account facts
35+
must degrade into named blockers or repairable issues.
36+
3037
In V26 fourth-gate this package is where merged-world Bitcode becomes concrete:
3138
- `/conversations` continuity
3239
- `/executions` compatibility and pipeline-run APIs

packages/api/src/routes/__tests__/auxillaries-contract.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ describe('Auxillaries package route contracts', () => {
1616
id: 'user-1',
1717
username: 'operator',
1818
display_name: 'Operator',
19+
email: 'operator@bitcode.exchange',
20+
is_verified: true,
1921
company_name: 'Bitcode',
2022
role: 'admin',
2123
wallet_binding: {
@@ -78,14 +80,55 @@ describe('Auxillaries package route contracts', () => {
7880
],
7981
modelPreferences: {
8082
preferred_model: 'gpt-4.1',
83+
preferred_provider: 'openai',
8184
},
85+
templatePreferences: {
86+
shippable_templates: {
87+
asset_pack_pr: { label: 'AssetPack PR' },
88+
},
89+
evidence_document_templates: {
90+
witness_summary: { label: 'Witness summary' },
91+
},
92+
auto_save_templates: true,
93+
},
94+
notificationRows: [
95+
{
96+
id: 'notification-1',
97+
is_read: false,
98+
created_at: '2026-05-21T01:00:00.000Z',
99+
},
100+
],
82101
onboardedSteps: ['btd', 'connects', 'profile', 'interfaces'],
83102
});
84103

85104
expect(payload.isOnboardingComplete).toBe(true);
86105
expect(payload.onboardedPanes).toEqual(['wallet', 'externals', 'profile', 'interfaces']);
87106
expect(payload.organizations).toEqual(['bitcode']);
88107
expect(payload.profileState.kind).toBe('AuxillariesProfileState');
108+
expect(payload.profileState.accountIdentity).toMatchObject({
109+
userId: 'user-1',
110+
emailVerified: true,
111+
});
112+
expect(payload.profileState.preferences.model).toMatchObject({
113+
configured: true,
114+
provider: 'openai',
115+
model: 'gpt-4.1',
116+
});
117+
expect(payload.profileState.preferences.templates).toMatchObject({
118+
configured: true,
119+
shippableTemplateCount: 1,
120+
evidenceDocumentTemplateCount: 1,
121+
autoSaveTemplates: true,
122+
});
123+
expect(payload.profileState.notificationPosture).toMatchObject({
124+
state: 'attention_needed',
125+
unreadCount: 1,
126+
});
127+
expect(payload.profileState.dataSharingPosture).toMatchObject({
128+
state: 'configured',
129+
repositoryCount: 1,
130+
enabledRepositoryCount: 1,
131+
});
89132
expect(payload.connectionReadiness[0]).toMatchObject({
90133
provider: 'github',
91134
connected: true,
@@ -124,6 +167,8 @@ describe('Auxillaries package route contracts', () => {
124167
btcFeeBalance: null,
125168
recentBtdAssetPacks: [],
126169
modelPreferences: null,
170+
templatePreferences: null,
171+
notificationRows: [],
127172
onboardedSteps: [],
128173
});
129174

@@ -134,6 +179,8 @@ describe('Auxillaries package route contracts', () => {
134179
expect(blockerIds).toEqual(expect.arrayContaining([
135180
'profile.missing',
136181
'profile.identity_missing',
182+
'preferences.model_missing',
183+
'preferences.templates_missing',
137184
'connects.github.connect_provider',
138185
'wallet.binding_missing',
139186
]));

0 commit comments

Comments
 (0)