Skip to content

Commit 2f80ea9

Browse files
Merge version/v28 into Gate 7
Resolve Gate 6 to Gate 7 conflicts after registry access policy landed on version/v28. The resolution preserves Gate 7's BTD exports and Jest module mappers while adopting Gate 6's BTD typecheck script and newer Jest dependency ranges. The lockfile remains frozen-consistent.
2 parents 825650e + 8179229 commit 2f80ea9

25 files changed

Lines changed: 1266 additions & 60 deletions

BITCODE_SPEC_V28.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,14 @@ Acceptance criteria:
709709
- policy templates cover owner-read, licensed-read, derivative use, redistribution, confidentiality, dispute, and takedown posture.
710710
- Terminal copy avoids price-appreciation, dividend, copyright-transfer, or marketplace-royalty promises.
711711

712+
Implementation posture:
713+
714+
- Organization `$BTD` posture is a registry projection. Read models must collect member wallet bindings, then read ownership events and read-license rows from the BTD registry. Aggregate compatibility balances may remain contextual but must not admit organization, MCP, ChatGPT App, or read-license actions.
715+
- MCP admission may require current owner-read or licensed-read evidence for one or more AssetPacks. Deprecated aggregate holding gates must fail closed and point callers to registry-derived read-access requirements.
716+
- ChatGPT App write-capable connected-interface tools must require explicit user confirmation and typed read-access evidence carrying AssetPack id, wallet id, owner-read or licensed-read decision, policy hash, and reason.
717+
- Access-policy templates must remain source-readable and test-covered for owner-read, licensed-read, derivative use, redistribution, confidentiality, dispute, and takedown posture.
718+
- Active Terminal and Auxillaries copy must describe registry, range, ownership, license, and proof posture without implying price appreciation, dividends, copyright transfer, or marketplace royalties.
719+
712720
### Gate 7: Terminal Operations And Testnet Readiness
713721

714722
Purpose:

internal-docs/BITCODE_CHATGPT_APP_INTERFACE.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,20 @@ It must not:
1919
- own Exchange state,
2020
- bypass Terminal/Exchange proof requirements,
2121
- write unconfirmed connected-interface changes,
22+
- write connected-interface changes without owner-read or licensed-read registry evidence for the relevant AssetPack,
2223
- use generic work-board examples as Bitcode product semantics.
2324

25+
## Gate 6 Read-Access Admission
26+
27+
Write-capable ChatGPT App tools require two independent admission facts:
28+
29+
- `confirmed: true` from the user interaction.
30+
- `readAccess` evidence with AssetPack id, wallet id, decision, access-policy hash, and reason.
31+
32+
The only admitted write decisions are `owner_read` and `licensed_read`. A balance,
33+
organization total, or generic account role is not enough to write through a
34+
connected interface.
35+
2436
## Requirements For SPEC Promotion
2537

2638
- tool names must be Bitcode-specific,

internal-docs/BITCODE_CONNECTED_SERVICES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ Examples:
2222
- Source providers bind evidence and repository scope.
2323
- Delivery providers receive AssetPacks or AssetPack partials.
2424
- Every write-capable connected interface must fail closed without readiness and admission receipts.
25+
- MCP and ChatGPT App writes must admit against owner-read or licensed-read registry evidence, not aggregate `$BTD` holding thresholds.
26+
- Organization `$BTD` posture must read member wallet bindings through BTD registry ownership and read-license rows.
2527
- Provider payloads must normalize toward Read, fit, AssetPack, settlement, proof, or delivery-mechanism semantics.
2628

2729
## Current Source Examples

packages/btd/__tests__/btd.test.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@ import {
99
BtdFungibleMutationRejectedError,
1010
BTD_MAX_MINTABLE_SUPPLY,
1111
BITCODE_FEE_ASSET,
12+
assertBtdAccessPolicyTemplateCoverage,
1213
assertBtdMintableSupplyLimit,
14+
buildBtdReadAccessProjectionFromRegistryRows,
1315
calculateLlmBtcFeeEstimate,
1416
calculateMeasuredBtdFromTokens,
17+
evaluateBtdReadAccess,
18+
listBtdAccessPolicyTemplates,
1519
} from '../src';
1620

1721
describe('calculateLlmBtcFeeEstimate', () => {
@@ -63,3 +67,101 @@ describe('BtdFungibleMutationRejectedError', () => {
6367
expect(err.code).toBe('BTD_IS_NON_FUNGIBLE');
6468
});
6569
});
70+
71+
describe('BTD access policy templates', () => {
72+
it('covers owner-read, licensed-read, policy, dispute, and takedown posture', () => {
73+
const templates = assertBtdAccessPolicyTemplateCoverage(listBtdAccessPolicyTemplates());
74+
75+
expect(templates.map((template) => template.kind)).toEqual(
76+
expect.arrayContaining([
77+
'owner_read',
78+
'licensed_read',
79+
'derivative_use',
80+
'redistribution',
81+
'confidentiality',
82+
'dispute',
83+
'takedown',
84+
]),
85+
);
86+
expect(templates.flatMap((template) => template.prohibitedClaims)).toEqual(
87+
expect.arrayContaining([
88+
'price appreciation',
89+
'dividend',
90+
'copyright transfer',
91+
'marketplace royalty',
92+
]),
93+
);
94+
});
95+
});
96+
97+
describe('registry-derived read access projection', () => {
98+
it('maps range, ownership, and read-license rows into owner-read decisions', () => {
99+
const projection = buildBtdReadAccessProjectionFromRegistryRows({
100+
assetPackId: 'asset-pack-1',
101+
range: {
102+
asset_pack_id: 'asset-pack-1',
103+
range_start: 10,
104+
range_end_exclusive: 15,
105+
token_count: 5,
106+
access_policy_id: 'policy-1',
107+
access_policy_hash: 'policy-hash',
108+
},
109+
ownershipRows: [
110+
{
111+
to_wallet_id: 'wallet-owner',
112+
asset_pack_id: 'asset-pack-1',
113+
range_start: 10,
114+
range_end_exclusive: 15,
115+
access_policy_hash: 'policy-hash',
116+
},
117+
],
118+
});
119+
120+
const decision = evaluateBtdReadAccess({
121+
walletId: 'wallet-owner',
122+
assetPackId: 'asset-pack-1',
123+
accessPolicy: projection.accessPolicy,
124+
ownershipClaims: projection.ownershipClaims,
125+
licenses: projection.licenses,
126+
at: '2026-05-19T00:00:00.000Z',
127+
});
128+
129+
expect(projection.range.tokenCount).toBe(5);
130+
expect(decision.decision).toBe('owner_read');
131+
});
132+
133+
it('maps registry read-license rows into licensed-read decisions', () => {
134+
const projection = buildBtdReadAccessProjectionFromRegistryRows({
135+
assetPackId: 'asset-pack-1',
136+
range: {
137+
asset_pack_id: 'asset-pack-1',
138+
range_start: 10,
139+
range_end_exclusive: 15,
140+
token_count: 5,
141+
access_policy_id: 'policy-1',
142+
access_policy_hash: 'policy-hash',
143+
},
144+
licenseRows: [
145+
{
146+
license_id: 'license-1',
147+
wallet_id: 'wallet-reader',
148+
asset_pack_id: 'asset-pack-1',
149+
access_policy_hash: 'policy-hash',
150+
valid_from: '2026-05-01T00:00:00.000Z',
151+
expires_at: '2026-06-01T00:00:00.000Z',
152+
},
153+
],
154+
});
155+
156+
const decision = evaluateBtdReadAccess({
157+
walletId: 'wallet-reader',
158+
assetPackId: 'asset-pack-1',
159+
accessPolicy: projection.accessPolicy,
160+
ownershipClaims: projection.ownershipClaims,
161+
licenses: projection.licenses,
162+
at: '2026-05-19T00:00:00.000Z',
163+
});
164+
165+
expect(decision.decision).toBe('licensed_read');
166+
});
167+
});

packages/btd/jest.config.cjs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
module.exports = {
22
preset: 'ts-jest',
33
testEnvironment: 'node',
4+
rootDir: '.',
45
roots: ['<rootDir>/__tests__'],
56
testMatch: ['<rootDir>/__tests__/**/*.test.ts'],
67
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
78
transform: {
8-
'^.+\\.[jt]sx?$': ['ts-jest', {
9-
tsconfig: {
10-
target: 'ES2020',
11-
module: 'CommonJS',
12-
esModuleInterop: true,
13-
skipLibCheck: true,
9+
'^.+\\.tsx?$': [
10+
'ts-jest',
11+
{
12+
tsconfig: '<rootDir>/tsconfig.json',
13+
diagnostics: false,
1414
},
15-
}],
15+
],
1616
},
1717
moduleNameMapper: {
1818
'^@bitcode/models/src/(.+)$': '<rootDir>/../models/src/$1',

packages/btd/package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,18 @@
99
"./terminal-operational-health": "./src/terminal-operational-health.ts"
1010
},
1111
"scripts": {
12-
"test": "jest --config jest.config.cjs --runInBand"
12+
"test": "jest --config jest.config.cjs --runInBand",
13+
"typecheck": "tsc --noEmit --pretty false"
1314
},
1415
"dependencies": {
1516
"@bitcode/models": "workspace:*",
1617
"@bitcode/supabase": "workspace:*"
1718
},
1819
"devDependencies": {
19-
"@types/jest": "^29.0.0",
20+
"@types/jest": "^29.5.12",
2021
"@types/node": "^20.0.0",
21-
"jest": "^29.0.0",
22-
"ts-jest": "^29.0.0",
22+
"jest": "^29.7.0",
23+
"ts-jest": "^29.1.1",
2324
"typescript": "^5.0.0"
2425
}
2526
}

0 commit comments

Comments
 (0)