|
1 | 1 | import { |
2 | 2 | acceptReadNeed, |
3 | 3 | admitNeedFitSearch, |
| 4 | + buildAssetPackSourceSafePreview, |
4 | 5 | buildShareToFeePreview, |
5 | 6 | isAcceptedReadNeed, |
6 | 7 | readNeedToDepositorySearchRead, |
| 8 | + resolveAssetPackReadRightState, |
7 | 9 | synthesizeReadNeedForPipelineInput, |
8 | 10 | } from '../read-need'; |
9 | | -import { runDepositorySearchForPipelineInput } from '../depository-search'; |
| 11 | +import { |
| 12 | + buildDepositoryFitResultEvidence, |
| 13 | + runDepositorySearchForPipelineInput, |
| 14 | +} from '../depository-search'; |
10 | 15 |
|
11 | 16 | const input = { |
12 | 17 | read: { |
@@ -136,6 +141,86 @@ describe('Read-Need synthesis and Need-Fit admission', () => { |
136 | 141 | finalityState: 'preview_not_paid', |
137 | 142 | payer: 'reader', |
138 | 143 | }); |
| 144 | + expect(preview.feeSchedule).toMatchObject({ |
| 145 | + satsPerWeightedVolume: 1000, |
| 146 | + minimumSats: 546, |
| 147 | + dustFloorSats: 546, |
| 148 | + networkFeePosture: 'reader_wallet_authorized_before_broadcast', |
| 149 | + }); |
| 150 | + expect(preview.measurementVector).toBe(acceptedReadNeed.pricingMeasurementInputs.measurementVector); |
| 151 | + expect(preview.quoteRoot).toMatch(/^sha256:/); |
139 | 152 | expect(preview.sats).toBeGreaterThanOrEqual(546); |
140 | 153 | }); |
| 154 | + |
| 155 | + it('builds a source-safe AssetPack preview without unlocking protected source', async () => { |
| 156 | + const acceptedReadNeed = acceptReadNeed( |
| 157 | + synthesizeReadNeedForPipelineInput(input), |
| 158 | + '2026-05-18T00:00:00.000Z' |
| 159 | + ); |
| 160 | + const search = await runDepositorySearchForPipelineInput({ |
| 161 | + ...input, |
| 162 | + acceptedReadNeed, |
| 163 | + requireAcceptedReadNeed: true, |
| 164 | + depositoryAssets: [depositoryAsset()], |
| 165 | + }); |
| 166 | + const fitResult = buildDepositoryFitResultEvidence(search); |
| 167 | + const preview = buildAssetPackSourceSafePreview({ |
| 168 | + need: acceptedReadNeed, |
| 169 | + fitResult, |
| 170 | + rangeStart: 42, |
| 171 | + pullRequestTarget: 'https://github.com/engineeredsoftware/ENGI/pull/6', |
| 172 | + createdAt: '2026-05-18T00:00:00.000Z', |
| 173 | + }); |
| 174 | + |
| 175 | + expect(preview).toMatchObject({ |
| 176 | + schema: 'bitcode.asset-pack.source-safe-preview', |
| 177 | + need: { |
| 178 | + needId: acceptedReadNeed.needId, |
| 179 | + measurementRoot: acceptedReadNeed.measurementRoot, |
| 180 | + reviewState: 'accepted', |
| 181 | + }, |
| 182 | + fit: { |
| 183 | + resultState: 'worthy_fit', |
| 184 | + selectedCandidateAssetIds: ['deposit-asset-1'], |
| 185 | + }, |
| 186 | + disclosurePolicy: { |
| 187 | + protectedSourceDisclosure: 'forbidden_before_settlement', |
| 188 | + }, |
| 189 | + settlementBoundary: { |
| 190 | + payer: 'reader', |
| 191 | + payee: 'depositor', |
| 192 | + serverCustody: false, |
| 193 | + ownershipTruth: 'asset_pack_range_and_license_rows', |
| 194 | + }, |
| 195 | + unlock: { |
| 196 | + state: 'pending_settlement', |
| 197 | + sourceAvailable: false, |
| 198 | + }, |
| 199 | + delivery: { |
| 200 | + pullRequestTarget: 'https://github.com/engineeredsoftware/ENGI/pull/6', |
| 201 | + availableAfterSettlement: true, |
| 202 | + }, |
| 203 | + }); |
| 204 | + expect(preview.roots.previewRoot).toMatch(/^sha256:/); |
| 205 | + expect(preview.roots.sourceManifestRoot).toMatch(/^sha256:/); |
| 206 | + expect(preview.feeQuote.quoteRoot).toMatch(/^sha256:/); |
| 207 | + expect(preview.rangeProjection).toMatchObject({ |
| 208 | + status: 'projected_not_minted', |
| 209 | + rangeStart: 42, |
| 210 | + }); |
| 211 | + expect(preview.rangeProjection.rangeEndExclusive).toBe( |
| 212 | + preview.rangeProjection.rangeStart! + preview.rangeProjection.tokenCount |
| 213 | + ); |
| 214 | + expect(preview.disclosurePolicy.withheldBeforeSettlement).toContain('protected source content'); |
| 215 | + }); |
| 216 | + |
| 217 | + it('keeps owner, licensed, pending-settlement, and denied read rights distinct', () => { |
| 218 | + expect(resolveAssetPackReadRightState({ hasOwnerClaim: true })).toBe('owner_read'); |
| 219 | + expect(resolveAssetPackReadRightState({ |
| 220 | + hasReadLicense: true, |
| 221 | + settlementReadbackComplete: true, |
| 222 | + })).toBe('licensed_read'); |
| 223 | + expect(resolveAssetPackReadRightState({ settlementPending: true })).toBe('pending_settlement'); |
| 224 | + expect(resolveAssetPackReadRightState({ policyDenied: true })).toBe('denied'); |
| 225 | + }); |
141 | 226 | }); |
0 commit comments