Skip to content

Commit ea509bf

Browse files
wip v28
1 parent 675216b commit ea509bf

18 files changed

Lines changed: 604 additions & 19 deletions

File tree

BITCODE_SPEC_V28_NOTES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ They are V28 inputs because V27 closed the protocol law and minimum crypto-comme
269269
| V26 proof generator and older promotion scripts still contain version-specific historical logic | V27 accepted generated-equivalent proof artifacts rather than fully modernizing promotion automation | Decide whether V28 should update proof generation for V28+ families or leave older promotion scripts as historical tooling |
270270
| Some formal protocol package internals are freshly ported from the standalone demonstration | V28 now owns commercializing the Protocol implementation enough that commercial code must not depend on demonstration runtime code | Keep commercial UAPI imports on formal packages such as `@bitcode/protocol`, keep `protocol-demonstration` out of the workspace build graph, move required demonstration-derived behavior into packages/UAPI, and use the demonstration only as reference/proof witness |
271271
| BNB Chain, opBNB, Binance Web3 Wallet, BEP-20, and BitVM bridge research are relevant but not current chain-of-record facts | V28 must avoid implying a public BTD deployment or native BNB Taproot/BitVM compatibility | Treat Bitcoin Taproot/PSBT/testnet as V28's practical crypto lane; record BSC/opBNB/Binance and BitVM bridge pilots as future bridge/distribution work unless a proof-bound testnet artifact exists |
272+
| Top chrome can briefly show `Connect Wallet` while wallet/user data is still loading | V28 wallet identity is the origin point for Supabase synchronization and Terminal readiness | Treat top chrome wallet state as tri-state: reading, connected, disconnected. The disconnected CTA may render only after auxillary user data has settled. While unresolved, render an integrated loading indicator and emit QA telemetry so manual passes can distinguish slow readiness from missing identity. |
273+
| Manual QA needs database-level evidence, not only screenshots | V28 is proving ledger/database synchronization posture before deeper deployment versions | Each wallet/GitHub/Terminal pass must collect client logs, server logs, network failures, and Supabase SQL query results for `auth.users`, `auth.identities`, `user_profiles`, `user_connections`, and repository inventory tables. Missing tables or permission errors are valid evidence and must be recorded, not hidden. |
272274

273275
## V28 Gate Sketch
274276

@@ -282,6 +284,9 @@ The minimum useful V28 gate plan is Protocol/Terminal-MVP-first:
282284

283285
2. **Gate 2: Protocol/Terminal MVP QA Baseline**
284286
- QA primary active routes and navigation.
287+
- Prove top chrome wallet readiness as a tri-state loading/connected/disconnected surface so the wallet CTA does not appear before connection status is known.
288+
- Add client and server QA telemetry around wallet OAuth, wallet proof persistence, auxillary data reads, GitHub setup callbacks, and user-data cache revalidation.
289+
- Add Supabase SQL verification to manual QA steps so profile, wallet identity, provider connection, and GitHub installation synchronization are checked at the database layer.
285290
- Remove Auxillaries old orbital shell conflicts from active contained tabs-left paths.
286291
- Disable or hide Exchange and website Conversations from V28 QA.
287292
- Separate commercial runtime imports from the standalone protocol demonstration and remove the demonstration from the workspace build graph.

BITCODE_V28_QA.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Each pass should be small enough to produce actionable screenshots, console obse
8585
| Pass | Track | Scope | Stop condition |
8686
| --- | --- | --- | --- |
8787
| 3A | Natural progression 1A | Wallet, GitHub, profile, notifications, nav balance, Auxillaries Connects/Profile/BTD readiness. | Mock passes deterministic readiness; testnet-readiness either works live or records precise blocked provider/credential states; no console errors. |
88+
| 3A-prereq | Natural progression 1A | Sign-up/sign-in, signed Bitcoin wallet authentication, BTC/BTD chrome, GitHub App installation, and prerequisite clarity before Give/Need. | Mock proves the intended prerequisite model; testnet proves or precisely blocks Supabase custom Bitcoin OAuth, wallet proof capture, profile persistence, sign-out clearing, and GitHub installation visibility. |
8889
| 3B | Natural progression 1B | Simplest Need path: select/express Need, run or inspect fastest Fit path, read settlement/delivery/result state. | User can explain what happened, where it landed in Exchange, what is mocked, and what remains staged in testnet-readiness. |
8990
| 3C | Natural progression 1C | Simplest Give path: attach or select source, run/inspect Give flow, read earning/settlement state. | User can explain what source was contributed, how it was measured, and whether earning/BTD posture is live, mocked, or blocked. |
9091
| 4A | Docs sequence 00 | Docs overview and Source Shares against nav, Terminal, BTD widget, MCP/ChatGPT readiness. | Contradictions between docs and product are logged in both lanes. |
@@ -208,6 +209,32 @@ Manual evidence requested for this pass:
208209
- console errors and network errors after each lane;
209210
- answer whether any wallet-extension permission prompt appeared, which wallet extension/provider it was, which network/account was selected, and whether the app changed state after approval/cancel/failure.
210211

212+
### 2026-05-12 Pass 3A-prereq: Sign-up, Sign-in, Wallet, And GitHub Prerequisites
213+
214+
This pass focuses only on prerequisite reality before Terminal Give/Need QA continues.
215+
It validates the V28 rule that signed Bitcoin wallet authentication is the origin point for Supabase user data synchronization, and that GitHub App installation is the next required prerequisite for Giving and Needing.
216+
217+
Run the same checklist first in mock, then in testnet-readiness.
218+
Mock establishes the intended product language and visual state.
219+
Testnet-readiness establishes whether the live custom OAuth provider, browser wallet, Supabase session, local/server wallet persistence, BTC/BTD chrome, sign-out clearing, and GitHub App install flow are usable or precisely blocked.
220+
221+
Prerequisite pass stop conditions:
222+
223+
| Lane | Stop condition |
224+
| --- | --- |
225+
| Mock | Profile shows wallet-first identity, Connects shows GitHub as the second prerequisite, BTD/top chrome show deterministic wallet facts, sign-out clears the signed-in mock posture, and no console errors appear. |
226+
| Testnet-readiness | A Bitcoin wallet proof either creates a Supabase session and persists through `/api/wallet/authenticate`, or fails at a named boundary: wallet provider unavailable, OAuth provider URL not reachable by Supabase, database schema missing, or GitHub App install/session missing. |
227+
228+
V28 prerequisite report fields:
229+
230+
1. Current URLs for both lanes and whether each route loaded at the top of `/terminal`.
231+
2. Mock Profile result: wallet-first copy, provider buttons, optional email position, BTC/BTD chrome, sign-out behavior, and console result.
232+
3. Testnet wallet result: provider clicked, wallet prompt seen, network/account selected, signed message approved/cancelled, final URL after Supabase callback, and whether Profile/top chrome show connected wallet.
233+
4. Testnet network/API result: any failed request URL/status/body for `/tps/wallet/authorize`, `/api/wallet/oauth/authorization-code`, Supabase `/auth/v1/token`, `/api/wallet/oauth/token`, `/api/wallet/oauth/userinfo`, `/api/wallet/authenticate`, `/api/auxillaries/data`, and GitHub callback/setup routes.
234+
5. Testnet sign-out result: whether Supabase session, local wallet identity, top chrome, Profile, BTD pane, and Connects prerequisite state all return to unauthenticated/unconnected.
235+
6. GitHub result: whether the install link opens `https://github.com/apps/bitcode-github-app-auxillary`, whether installation callback returns to Connects, and whether connected account/repository scope appears.
236+
7. Screenshots of any blocked/failing state and all console errors/warnings except expected extension-injection noise.
237+
211238
Manual findings from 2026-05-09:
212239

213240
| Lane | Check | Result | V28 disposition |
@@ -477,3 +504,119 @@ V28 blocker / V28 polish / V29+ deferred
477504

478505
### Notes
479506
```
507+
508+
## Required QA Telemetry And Database Evidence
509+
510+
Every V28 manual pass from this point forward must capture three evidence layers.
511+
512+
1. Browser console with `NEXT_PUBLIC_BITCODE_QA_VERBOSE=true`.
513+
Capture `[Bitcode QA]` lines after each interaction group, plus warnings/errors from wallet extensions, Supabase, GitHub, and route fetches.
514+
515+
2. Dev server console with `BITCODE_QA_VERBOSE=true`.
516+
Capture `[Bitcode QA Server]` lines for wallet OAuth, token/userinfo, wallet persistence, auxillary data reads, and GitHub callback/setup routes.
517+
518+
3. Supabase SQL results.
519+
Run the relevant SQL queries below after sign-in, sign-out, GitHub install, and any Terminal write that claims to sync identity/source state.
520+
Paste both successful rows and SQL/table/permission errors into the QA notes.
521+
522+
Wallet-authentication baseline:
523+
524+
```sql
525+
select
526+
id,
527+
email,
528+
raw_app_meta_data,
529+
raw_user_meta_data,
530+
created_at,
531+
last_sign_in_at
532+
from auth.users
533+
order by created_at desc
534+
limit 5;
535+
```
536+
537+
```sql
538+
select
539+
user_id,
540+
provider,
541+
identity_data,
542+
created_at,
543+
updated_at
544+
from auth.identities
545+
where provider = 'custom:bitcode-bitcoin'
546+
order by updated_at desc
547+
limit 10;
548+
```
549+
550+
Bitcode profile and wallet binding:
551+
552+
```sql
553+
select
554+
id,
555+
username,
556+
wallet_address,
557+
wallet_provider,
558+
wallet_binding_status,
559+
settings->'bitcodeProfile'->'walletBinding' as wallet_binding,
560+
updated_at
561+
from public.user_profiles
562+
order by updated_at desc
563+
limit 10;
564+
```
565+
566+
Wallet and GitHub provider connections:
567+
568+
```sql
569+
select
570+
user_id,
571+
provider,
572+
is_active,
573+
connection_data->>'address' as wallet_address,
574+
connection_data->>'network' as wallet_network,
575+
connection_data->>'verification_state' as verification_state,
576+
connection_data->>'auth_source' as auth_source,
577+
connection_data->>'account_login' as github_account,
578+
updated_at
579+
from public.user_connections
580+
where provider in ('xverse', 'leather', 'unisat', 'okx-bitcoin', 'github')
581+
order by updated_at desc
582+
limit 20;
583+
```
584+
585+
GitHub repository inventory:
586+
587+
```sql
588+
select
589+
user_id,
590+
provider,
591+
repo_full_name,
592+
repo_default_branch,
593+
updated_at
594+
from public.vcs_repositories
595+
order by updated_at desc
596+
limit 20;
597+
```
598+
599+
If `vcs_repositories` is not present in the current schema, run:
600+
601+
```sql
602+
select
603+
user_id,
604+
provider,
605+
connection_data->'repositories' as installation_repositories,
606+
updated_at
607+
from public.user_connections
608+
where provider = 'github'
609+
order by updated_at desc
610+
limit 10;
611+
```
612+
613+
### Top Chrome Wallet Readiness
614+
615+
Expected V28 behavior:
616+
617+
- first page load renders an integrated `Reading wallet` indicator while `/api/auxillaries/data` and local wallet identity state are unresolved;
618+
- `Connect Wallet` renders only after the data read has settled with no wallet identity;
619+
- the BTC/BTD widget renders only after a stored or locally staged wallet identity is known;
620+
- a later background revalidation may make the BTC/BTD widget show its own loading posture, but it must not regress to the disconnected CTA while a known wallet exists;
621+
- client telemetry must include `nav:chrome-identity`, `user-data:fetch-start`, `user-data:read` or `user-data:anonymous-read`, and any fetch failure;
622+
- server telemetry must include `auxillaries-data:read-start` and `auxillaries-data:read-finish` or `auxillaries-data:read-failed`.

uapi/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ It carries the `/terminal` operator surface, `/exchange` activity master-detail,
55

66
Active canon follows the top-level `BITCODE_SPEC.txt` pointer while the current draft hardens the commercial MVP experience.
77

8+
V28 QA scope is intentionally narrower than the full route inventory: Terminal, Auxillaries readiness, wallet-backed identity, GitHub source prerequisites, `$BTD` posture, MCP/API, and ChatGPT App MVP remain active; Exchange and website Conversations are deferred beyond V35 unless retained code contaminates the active V28 surfaces.
9+
Wallet state in top chrome is tri-state during QA: loading while shared auxillary data is unresolved, connected when a wallet binding or local staged wallet exists, and disconnected only after the read settles without a wallet.
10+
811
## Primary routes
912

1013
- `/`

uapi/app/api/auxillaries/data/route.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { buildGetAuxillaryDataRoute } from '@bitcode/api/src/routes/auxillaries';
22
import { buildMockAuxillariesData, isAuxillariesMockMode } from '@/lib/mock-review-mode';
3+
import { bitcodeServerTelemetry } from '@/lib/bitcode-server-telemetry';
34
import { readBitcodeWalletConnectionStatus } from '@/app/api/wallet/_shared';
45
import {
56
buildDisconnectedConnectionStatus,
@@ -11,7 +12,7 @@ import {
1112

1213
export const runtime = 'nodejs';
1314

14-
export const GET = buildGetAuxillaryDataRoute({
15+
const getAuxillaryData = buildGetAuxillaryDataRoute({
1516
isMockMode: isAuxillariesMockMode,
1617
mockAuxillaryData: buildMockAuxillariesData,
1718
resolveWalletConnectionStatus: async ({ supabase, userId, profile }) => {
@@ -48,3 +49,24 @@ export const GET = buildGetAuxillaryDataRoute({
4849
};
4950
},
5051
});
52+
53+
export async function GET(request: Request) {
54+
bitcodeServerTelemetry('info', 'auxillaries-data', 'read-start', {
55+
mockMode: isAuxillariesMockMode(),
56+
});
57+
58+
try {
59+
const response = await getAuxillaryData(request);
60+
bitcodeServerTelemetry('info', 'auxillaries-data', 'read-finish', {
61+
status: response.status,
62+
mockMode: isAuxillariesMockMode(),
63+
});
64+
return response;
65+
} catch (error) {
66+
bitcodeServerTelemetry('error', 'auxillaries-data', 'read-failed', {
67+
message: error instanceof Error ? error.message : String(error),
68+
mockMode: isAuxillariesMockMode(),
69+
});
70+
throw error;
71+
}
72+
}

uapi/app/api/wallet/authenticate/route.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import {
66
} from '@bitcode/orm';
77
import { supabaseAdmin } from '@bitcode/supabase';
88
import { createClient } from '@bitcode/supabase/ssr/server';
9+
import {
10+
bitcodeServerTelemetry,
11+
compactBitcodeServerId,
12+
} from '@/lib/bitcode-server-telemetry';
913

1014
export const runtime = 'nodejs';
1115

@@ -80,6 +84,9 @@ export async function POST(request: Request) {
8084
} = await supabase.auth.getUser();
8185

8286
if (!user || userError) {
87+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'session-required', {
88+
userError: userError?.message ?? null,
89+
});
8390
return NextResponse.json(
8491
{
8592
error:
@@ -94,6 +101,7 @@ export async function POST(request: Request) {
94101
try {
95102
body = (await request.json()) as WalletAuthPayload;
96103
} catch {
104+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'invalid-json');
97105
return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 });
98106
}
99107

@@ -110,10 +118,19 @@ export async function POST(request: Request) {
110118
const connectedAt = readNonEmptyString(body.connectedAt) ?? issuedAt;
111119

112120
if (!address || !isPlausibleBitcoinAddress(address)) {
121+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'invalid-address', {
122+
address: compactBitcodeServerId(address),
123+
provider,
124+
network,
125+
});
113126
return NextResponse.json({ error: 'A valid Bitcoin wallet address is required.' }, { status: 400 });
114127
}
115128

116129
if (!provider) {
130+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'invalid-provider', {
131+
provider: readNonEmptyString(body.provider),
132+
address: compactBitcodeServerId(address),
133+
});
117134
return NextResponse.json(
118135
{
119136
error:
@@ -124,17 +141,29 @@ export async function POST(request: Request) {
124141
}
125142

126143
if (!proofKind) {
144+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'missing-proof-kind', {
145+
provider,
146+
address: compactBitcodeServerId(address),
147+
});
127148
return NextResponse.json({ error: 'Bitcoin wallet proof kind is required.' }, { status: 400 });
128149
}
129150

130151
if (proofKind === 'bitcoin_message_signature') {
131152
if (!message || !signature) {
153+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'missing-signature', {
154+
provider,
155+
address: compactBitcodeServerId(address),
156+
});
132157
return NextResponse.json(
133158
{ error: 'Bitcoin wallet message-signature proof requires both message and signature.' },
134159
{ status: 400 },
135160
);
136161
}
137162
if (!isBitcodeBitcoinWalletMessage(message, address)) {
163+
bitcodeServerTelemetry('warn', 'wallet-authenticate', 'message-mismatch', {
164+
provider,
165+
address: compactBitcodeServerId(address),
166+
});
138167
return NextResponse.json(
139168
{ error: 'Bitcoin wallet message does not match the Bitcode authentication challenge.' },
140169
{ status: 400 },
@@ -144,13 +173,26 @@ export async function POST(request: Request) {
144173

145174
const persistedAt = new Date().toISOString();
146175
const bindingStatus = proofKind === 'bitcoin_message_signature' ? 'pending' : 'pending';
176+
bitcodeServerTelemetry('info', 'wallet-authenticate', 'persist-start', {
177+
userId: compactBitcodeServerId(user.id),
178+
provider,
179+
address: compactBitcodeServerId(address),
180+
network,
181+
proofKind,
182+
paymentAddress: compactBitcodeServerId(paymentAddress),
183+
authAddress: compactBitcodeServerId(authAddress),
184+
});
147185
const { data: existingProfile, error: profileReadError } = await supabaseAdmin
148186
.from('user_profiles')
149187
.select('*')
150188
.eq('id', user.id)
151189
.maybeSingle();
152190

153191
if (profileReadError) {
192+
bitcodeServerTelemetry('error', 'wallet-authenticate', 'profile-read-failed', {
193+
userId: compactBitcodeServerId(user.id),
194+
message: profileReadError.message,
195+
});
154196
return NextResponse.json({ error: profileReadError.message }, { status: 500 });
155197
}
156198

@@ -190,6 +232,10 @@ export async function POST(request: Request) {
190232
);
191233

192234
if (profileWriteError) {
235+
bitcodeServerTelemetry('error', 'wallet-authenticate', 'profile-write-failed', {
236+
userId: compactBitcodeServerId(user.id),
237+
message: profileWriteError.message,
238+
});
193239
return NextResponse.json({ error: profileWriteError.message }, { status: 500 });
194240
}
195241

@@ -223,6 +269,12 @@ export async function POST(request: Request) {
223269
);
224270

225271
if (connectionWriteError) {
272+
bitcodeServerTelemetry('error', 'wallet-authenticate', 'connection-write-failed', {
273+
userId: compactBitcodeServerId(user.id),
274+
provider,
275+
address: compactBitcodeServerId(address),
276+
message: connectionWriteError.message,
277+
});
226278
return NextResponse.json(
227279
{
228280
error: connectionWriteError.message,
@@ -234,6 +286,14 @@ export async function POST(request: Request) {
234286
);
235287
}
236288

289+
bitcodeServerTelemetry('info', 'wallet-authenticate', 'persist-success', {
290+
userId: compactBitcodeServerId(user.id),
291+
provider,
292+
address: compactBitcodeServerId(address),
293+
network,
294+
verificationState: bindingStatus,
295+
});
296+
237297
return NextResponse.json(
238298
{
239299
success: true,

0 commit comments

Comments
 (0)