{"id":"bumpgrade-product-access-source-data","updatedAt":"2026-05-20","status":"subscription-membership-entitlement-ready","issue":187,"parentIssue":16,"generatedFrom":"src/lib/product-access.ts","routes":["/products/source-data","/products/entitlements","/api/products/entitlements","/api/products/download-tokens","/api/products/downloads?token={token}","/api/products/protected-content","/api/admin/products/assets","/api/admin/products/revocation-intents","/products/indie-launch-library"],"stableIds":["productId","assetId","accessRuleId","entitlementTemplateId","customerProductEntitlementLookupId","productDownloadTokenId","productAssetUploadIntentId","productEntitlementRevocationIntentId","productProtectedContentId","subscriptionPlanId","fulfillmentId","agentActionId"],"entitlementWrites":{"id":"product-entitlement-webhook-grant-contract","status":"sandbox-webhook-grants-ready","issue":101,"parentIssue":16,"sourceEvents":["checkout.session.completed"],"tables":["product_entitlements","product_fulfillment_tasks"],"sourceDataRoute":"/products/source-data","grantMappings":[{"id":"grant-map-sandbox-launch-pass-to-bundle","sourcePriceId":"price-bumpgrade-sandbox-launch-pass-usd","sourceCommerceProductId":"product-bumpgrade-sandbox-launch-pass","productId":"product-launch-bundle","productTitle":"Launch bundle","entitlementTemplateId":"entitlement-template-launch-bundle","entitlementTemplateTitle":"Launch bundle entitlement","accessRuleId":"access-rule-download-after-paid-webhook","fulfillmentKind":"bundle","grants":["Download access","Course enrollment","Membership access"],"grantSummary":"Grant the sandbox launch bundle entitlement after trusted paid checkout evidence."},{"id":"grant-map-launch-checklist-bump-to-download","sourcePriceId":"price-launch-checklist-bump-usd","sourceCommerceProductId":"product-launch-checklist-bump","productId":"product-launch-checklist-download","productTitle":"Launch checklist download","entitlementTemplateId":"entitlement-template-launch-download","entitlementTemplateTitle":"Launch download entitlement","accessRuleId":"access-rule-download-after-paid-webhook","fulfillmentKind":"digital_download","grants":["Download asset access","Receipt-visible fulfillment status"],"grantSummary":"Grant the launch checklist download entitlement after trusted paid checkout evidence."}],"publicSafeFields":["id","checkout_intent_id","product_id","entitlement_template_id","access_rule_id","status","grant_kind","source_price_id","granted_at"],"serverPrivateFields":["buyer_user_id","buyer_email_hash","source_stripe_event_id","metadata_json","private R2 object keys","signed URLs","raw Stripe customer/session/payment IDs"],"writeBoundary":"Issue #101 can grant idempotent sandbox entitlement rows from trusted paid checkout webhook evidence. Signed downloads, protected content, revocation, live fulfillment, customer portals, refunds, and direct agent writes remain locked behind future confirmed-write APIs."},"grantMappings":[{"id":"grant-map-sandbox-launch-pass-to-bundle","sourcePriceId":"price-bumpgrade-sandbox-launch-pass-usd","sourceCommerceProductId":"product-bumpgrade-sandbox-launch-pass","productId":"product-launch-bundle","productTitle":"Launch bundle","entitlementTemplateId":"entitlement-template-launch-bundle","entitlementTemplateTitle":"Launch bundle entitlement","accessRuleId":"access-rule-download-after-paid-webhook","fulfillmentKind":"bundle","grants":["Download access","Course enrollment","Membership access"],"grantSummary":"Grant the sandbox launch bundle entitlement after trusted paid checkout evidence."},{"id":"grant-map-launch-checklist-bump-to-download","sourcePriceId":"price-launch-checklist-bump-usd","sourceCommerceProductId":"product-launch-checklist-bump","productId":"product-launch-checklist-download","productTitle":"Launch checklist download","entitlementTemplateId":"entitlement-template-launch-download","entitlementTemplateTitle":"Launch download entitlement","accessRuleId":"access-rule-download-after-paid-webhook","fulfillmentKind":"digital_download","grants":["Download asset access","Receipt-visible fulfillment status"],"grantSummary":"Grant the launch checklist download entitlement after trusted paid checkout evidence."}],"subscriptionMembershipAccess":{"id":"subscription-membership-access-contract","status":"subscription-membership-entitlement-ready","issue":187,"parentIssue":16,"sourceEvents":["customer.subscription.created","customer.subscription.updated","customer.subscription.deleted"],"sourceDataRoute":"/products/source-data","customerLookupRoute":"/api/products/entitlements","sourcePriceId":"price-launch-membership-monthly-usd","sourceCommerceProductId":"product-bumpgrade-launch-membership","productId":"product-launch-membership","entitlementTemplateId":"entitlement-template-launch-membership","accessRuleId":"access-rule-membership-active-subscription","activeStatuses":["active","trialing"],"inactiveStatuses":["canceled","unpaid","incomplete_expired"],"redaction":{"buyerEmailIncluded":false,"buyerEmailHashIncluded":false,"rawStripeSubscriptionIdsIncluded":false,"rawStripeCustomerIdsIncluded":false,"sourceStripeEventIdsIncluded":false,"metadataJsonIncluded":false,"memberPostsIncluded":false,"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"progressDataIncluded":false,"customerPortalUrlIncluded":false},"writeBoundary":"Issue #187 mirrors trusted Stripe Billing subscription state and updates a checkout-linked membership entitlement only when subscription state is active or trialing. It marks access inactive when subscription state is canceled, unpaid, incomplete_expired, or deleted. It does not create manual renewal loops, Customer Portal sessions, raw Stripe ID exposure, member posts, progress rows, private R2 keys, signed URLs, destructive revocation, or direct unauthenticated agent writes.","source":"d1","loadError":null,"counts":{"billingSubscriptions":0,"activeOrTrialingBillingSubscriptions":0,"membershipEntitlements":0,"activeMembershipEntitlements":0,"inactiveMembershipEntitlements":0}},"subscriptionMembershipGrantMapping":{"id":"grant-map-launch-membership-subscription","sourcePriceId":"price-launch-membership-monthly-usd","sourceCommerceProductId":"product-bumpgrade-launch-membership","productId":"product-launch-membership","productTitle":"Launch membership","entitlementTemplateId":"entitlement-template-launch-membership","entitlementTemplateTitle":"Launch membership entitlement","accessRuleId":"access-rule-membership-active-subscription","fulfillmentKind":"membership","grants":["Member area access while subscription is active or trialing"],"grantSummary":"Grant launch membership access while trusted Stripe Billing subscription state is active or trialing."},"writeBoundary":"Issue #101 can grant idempotent sandbox product entitlement rows and fulfillment task evidence from trusted paid checkout webhooks, issue #141 can inspect customer-safe checkout-intent entitlement status, issue #143 can create one-use download tokens for active file entitlements, issue #146 can stream a seeded private R2-backed fixture through Bumpgrade, issue #147 revalidates current entitlement and trusted checkout state before redemption, issue #151 lets verified owners create small private asset upload records after exact confirmation, idempotency, and catalog revision checks, issue #179 exposes non-destructive revocation intent readiness, issue #181 exposes protected content readiness, issue #185 returns seeded protected fixture bodies only after checkout-intent, entitlement, product/template scope, and trusted checkout checks, issue #187 syncs checkout-linked membership entitlement state from trusted Stripe Billing subscription events, and issue #251 lets verified owners record non-destructive revocation intents after exact confirmation, idempotency, and stale-state checks. Product creation, customer delivery of arbitrary uploads, signed object URLs, refunds, Customer Portal actions, destructive revocations, live fulfillment automation, and direct unauthenticated agent writes require future APIs.","catalogs":[{"id":"product-access-catalog-indie-launch","slug":"indie-launch-library","title":"Indie launch product and access library","status":"draft","issue":101,"parentIssue":16,"sourceDataRoute":"/products/source-data","previewRoute":"/products/indie-launch-library","checkoutOfferRoute":"/offers/indie-launch-stack","commerceContractRoute":"/commerce/source-data","revisionId":"product-access-revision-indie-launch-2026-05-19","summary":"A product and access library for downloads, courses, memberships, services, events, bundles, payment-backed access, and protected delivery.","assets":[{"id":"asset-launch-checklist-pdf","kind":"file","title":"Launch checklist PDF","publicDescription":"A downloadable checklist asset delivered only after customer access is confirmed.","storageBoundary":"Issue #146 stores and reads the safe fixture through the PRODUCT_ASSETS R2 binding server-side; private object keys and signed URLs stay out of public source-data and token responses."},{"id":"asset-launch-course-lessons","kind":"lesson","title":"Launch course lessons","publicDescription":"Course lesson metadata for a future protected learning area.","storageBoundary":"Lesson bodies, videos, transcripts, and progress data remain private until auth and entitlements ship."},{"id":"asset-launch-member-area","kind":"member_area","title":"Launch member area","publicDescription":"Membership container for recurring access state.","storageBoundary":"Member-only posts, files, community data, and billing identifiers are not exposed in this source-data slice."},{"id":"asset-launch-coaching-booking","kind":"booking","title":"Launch coaching booking","publicDescription":"Manual scheduling path for service delivery.","storageBoundary":"Calendar links, private notes, buyer details, and meeting URLs stay server-private."},{"id":"asset-launch-webinar-seat","kind":"event","title":"Launch webinar seat","publicDescription":"Event access path for webinar or live workshop delivery.","storageBoundary":"Private join URLs, attendee lists, and replay URLs require confirmed entitlement state."}],"accessRules":[{"id":"access-rule-download-after-paid-webhook","title":"Grant download after paid checkout","grants":"Digital download access after trusted checkout completion.","timing":"after_webhook_paid","revocable":true,"sourceEvent":"checkout.session.completed","writeBoundary":"Issue #146 can issue a short-lived one-use token for active file entitlements and stream the seeded private R2 fixture through Bumpgrade."},{"id":"access-rule-course-after-paid-webhook","title":"Grant course after paid checkout","grants":"Course enrollment after paid checkout evidence.","timing":"after_webhook_paid","revocable":true,"sourceEvent":"checkout.session.completed","writeBoundary":"No protected lesson access or progress record is written in this slice."},{"id":"access-rule-membership-active-subscription","title":"Grant membership while subscription is active","grants":"Membership access while Stripe subscription state is active or trialing.","timing":"active_subscription","revocable":true,"sourceEvent":"customer.subscription.updated","writeBoundary":"No subscription entitlement is granted until billing subscription state is mirrored and trusted."},{"id":"access-rule-service-manual-review","title":"Queue service fulfillment for manual review","grants":"Service or coaching delivery task after payment evidence.","timing":"manual_review","revocable":true,"sourceEvent":"payment_audit_events","writeBoundary":"No private booking link, customer note, or meeting URL is exposed through public source-data."},{"id":"access-rule-event-after-paid-webhook","title":"Grant event seat after paid checkout","grants":"Event or webinar seat after trusted payment evidence.","timing":"after_webhook_paid","revocable":true,"sourceEvent":"checkout.session.completed","writeBoundary":"No join URL, attendee roster, or replay access is exposed until entitlement writes exist."}],"products":[{"id":"product-launch-checklist-download","slug":"launch-checklist-download","kind":"digital_download","title":"Launch checklist download","status":"draft","summary":"A downloadable asset that can back an order bump or standalone checkout product.","linkedOfferIds":["offer-bump-launch-checklist"],"assetIds":["asset-launch-checklist-pdf"],"accessRuleIds":["access-rule-download-after-paid-webhook"],"entitlementTemplateId":"entitlement-template-launch-download"},{"id":"product-launch-course-lite","slug":"launch-course-lite","kind":"course","title":"Launch course lite","status":"draft","summary":"A small course product for lessons, modules, and protected progress state.","linkedOfferIds":["offer-upsell-launch-accelerator"],"assetIds":["asset-launch-course-lessons"],"accessRuleIds":["access-rule-course-after-paid-webhook"],"entitlementTemplateId":"entitlement-template-launch-course"},{"id":"product-launch-membership","slug":"launch-membership","kind":"membership","title":"Launch membership","status":"draft","summary":"Recurring membership access that depends on subscription state.","linkedOfferIds":["offer-upsell-launch-accelerator"],"assetIds":["asset-launch-member-area"],"accessRuleIds":["access-rule-membership-active-subscription"],"entitlementTemplateId":"entitlement-template-launch-membership"},{"id":"product-launch-coaching-session","slug":"launch-coaching-session","kind":"coaching_service","title":"Launch coaching session","status":"draft","summary":"Manual service fulfillment path for coaching or implementation support.","linkedOfferIds":["offer-downsell-launch-review"],"assetIds":["asset-launch-coaching-booking"],"accessRuleIds":["access-rule-service-manual-review"],"entitlementTemplateId":"entitlement-template-launch-service"},{"id":"product-launch-webinar-seat","slug":"launch-webinar-seat","kind":"event_webinar","title":"Launch webinar seat","status":"draft","summary":"Event or webinar access record with private join details kept out of public data.","linkedOfferIds":["offer-downsell-launch-review"],"assetIds":["asset-launch-webinar-seat"],"accessRuleIds":["access-rule-event-after-paid-webhook"],"entitlementTemplateId":"entitlement-template-launch-event"},{"id":"product-launch-bundle","slug":"launch-bundle","kind":"bundle","title":"Launch bundle","status":"draft","summary":"Bundle model that can grant multiple product entitlements after a trusted purchase.","linkedOfferIds":["offer-upsell-launch-accelerator"],"assetIds":["asset-launch-checklist-pdf","asset-launch-course-lessons","asset-launch-member-area"],"accessRuleIds":["access-rule-download-after-paid-webhook","access-rule-course-after-paid-webhook","access-rule-membership-active-subscription"],"entitlementTemplateId":"entitlement-template-launch-bundle"}],"entitlementTemplates":[{"id":"entitlement-template-launch-download","title":"Launch download entitlement","productIds":["product-launch-checklist-download"],"status":"draft","grants":["Download asset access","Receipt-visible fulfillment status"],"revocationRules":["Refunds or chargebacks should revoke download eligibility in a future fulfillment API."],"privateDataExcluded":["R2 object key","signed URL","buyer email","Stripe customer id"]},{"id":"entitlement-template-launch-course","title":"Launch course entitlement","productIds":["product-launch-course-lite"],"status":"draft","grants":["Course enrollment","Protected lesson access"],"revocationRules":["Refund, dispute, or manual admin revocation should remove future lesson access."],"privateDataExcluded":["Lesson body","video URL","progress state","buyer identity"]},{"id":"entitlement-template-launch-membership","title":"Launch membership entitlement","productIds":["product-launch-membership"],"status":"draft","grants":["Member area access while subscription is active"],"revocationRules":["Subscription cancellation, unpaid invoices, refunds, or disputes should revoke active access."],"privateDataExcluded":["Stripe subscription id","member posts","private files","buyer identity"]},{"id":"entitlement-template-launch-service","title":"Launch service entitlement","productIds":["product-launch-coaching-session"],"status":"draft","grants":["Manual service fulfillment task"],"revocationRules":["Service cancellation or refund should close or reverse the fulfillment task."],"privateDataExcluded":["Calendar link","meeting URL","private notes","buyer identity"]},{"id":"entitlement-template-launch-event","title":"Launch event entitlement","productIds":["product-launch-webinar-seat"],"status":"draft","grants":["Event seat","Replay eligibility after event"],"revocationRules":["Refund, cancellation, or no-show policy should determine event access changes."],"privateDataExcluded":["Join URL","attendee list","replay URL","buyer identity"]},{"id":"entitlement-template-launch-bundle","title":"Launch bundle entitlement","productIds":["product-launch-bundle"],"status":"draft","grants":["Download access","Course enrollment","Membership access"],"revocationRules":["Bundle revocation should cascade through each component entitlement with audit evidence."],"privateDataExcluded":["Component private asset keys","subscription ids","buyer identity"]}],"writeBoundary":"Issue #101 can grant idempotent sandbox product entitlement rows and fulfillment task evidence from trusted paid checkout webhooks, issue #141 can inspect customer-safe checkout-intent entitlement status, issue #143 can create one-use download tokens for active file entitlements, issue #146 can stream a seeded private R2-backed fixture through Bumpgrade, issue #147 revalidates current entitlement and trusted checkout state before redemption, issue #151 lets verified owners create small private asset upload records after exact confirmation, idempotency, and catalog revision checks, issue #179 exposes non-destructive revocation intent readiness, issue #181 exposes protected content readiness, issue #185 returns seeded protected fixture bodies only after checkout-intent, entitlement, product/template scope, and trusted checkout checks, issue #187 syncs checkout-linked membership entitlement state from trusted Stripe Billing subscription events, and issue #251 lets verified owners record non-destructive revocation intents after exact confirmation, idempotency, and stale-state checks. Product creation, customer delivery of arbitrary uploads, signed object URLs, refunds, Customer Portal actions, destructive revocations, live fulfillment automation, and direct unauthenticated agent writes require future APIs.","validation":["/products/source-data returns seeded products, assets, access rules, and entitlement templates.","/products/indie-launch-library renders the product/access preview.","/products/entitlements renders checkout-intent-scoped customer entitlement lookup.","/api/products/download-tokens creates short-lived download tokens for active file entitlements.","/api/products/downloads?token={token} revalidates current entitlement and trusted checkout state, streams the seeded private R2 fixture once, and rejects token replay.","/api/admin/products/assets lets verified owners create small private R2-backed asset upload records without exposing private object keys, signed URLs, or upload bodies.","Owner-confirmed revocation intents are recordable without entitlement mutation, access removal, raw buyer exposure, billing changes, refunds, or customer notification.","Protected content readiness is inspectable without lesson bodies, member posts, progress rows, private R2 keys, signed URLs, or customer delivery.","Subscription-backed membership access is inspectable without raw Stripe subscription/customer IDs, buyer identity, member posts, private files, or Customer Portal URLs.","/api/stripe/webhook grants idempotent sandbox entitlements after trusted paid checkout evidence.","/agent-docs/source-data lists the product access read contract for future MCP resources."]}],"caveat":"This contract proves product/access read and preview semantics, sandbox webhook-backed entitlement row grants, subscription-backed membership entitlement state, owner inspection, customer-safe checkout-intent entitlement lookup, short-lived download tokens, seeded private R2-backed fixture delivery, owner-confirmed small private asset upload records, owner-confirmed non-destructive revocation intent records, protected content readiness, and checkout-intent-scoped protected fixture delivery. It does not expose private R2 keys, signed object URLs, upload bodies, arbitrary uploaded content, private revocation notes, raw Stripe subscription/customer IDs, destructive revocation APIs, live fulfillment automation, customer portals, customer delivery of arbitrary uploads, or direct unauthenticated agent writes.","entitlementInspection":{"id":"product-entitlement-inspection-contract","status":"owner-product-entitlement-inspection-ready","issue":139,"parentIssue":16,"ownerRoute":"/admin/products","publicSourceDataRoute":"/products/source-data","source":"d1","loadError":null,"counts":{"entitlements":8,"activeEntitlements":8,"fulfillmentTasks":8,"queuedFulfillmentTasks":8,"checkoutIntentsWithEntitlements":4},"lastGrantedAt":"2026-05-19T12:23:59.000Z","lastFulfillmentAt":"2026-05-19T12:23:59.000Z","productCounts":[{"id":"product-launch-bundle","status":"active","total":4},{"id":"product-launch-checklist-download","status":"active","total":4}],"templateCounts":[{"id":"entitlement-template-launch-bundle","status":"active","total":4},{"id":"entitlement-template-launch-download","status":"active","total":4}],"fulfillmentCounts":[{"id":"bundle","status":"queued","total":4},{"id":"digital_download","status":"queued","total":4}],"redaction":{"privateBuyerDataIncluded":false,"rawBuyerEmailIncluded":false,"buyerEmailHashIncluded":false,"rawStripeIdsIncluded":false,"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"metadataJsonIncluded":false},"privateFieldsExcluded":["buyerEmail","buyerEmailHash","sourceStripeEventId","stripeCheckoutSessionId","stripePaymentIntentId","stripeSubscriptionId","metadataJson","privateR2ObjectKeys","signedUrls"],"writeBoundary":"Issue #139 exposes owner-gated product entitlement and fulfillment inspection plus public aggregate source-data. Signed downloads, protected lessons, revocations, subscription access changes, refunds, customer portals, private asset delivery, and direct agent entitlement writes still require future confirmed-write APIs."},"customerEntitlementLookup":{"id":"customer-product-entitlement-lookup-contract","status":"customer-product-entitlement-lookup-ready","issue":141,"parentIssue":16,"route":"/products/entitlements","apiRoute":"/api/products/entitlements","sourceDataRoute":"/products/source-data","authBoundary":"checkout-intent-bearer-reference","lookupInput":"checkoutIntentId","redaction":{"buyerEmailIncluded":false,"buyerEmailHashIncluded":false,"rawStripeIdsIncluded":false,"sourceStripeEventIdsIncluded":false,"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"metadataJsonIncluded":false,"downloadTokensIncluded":false},"privateFieldsExcluded":["buyerEmail","buyerEmailHash","buyerUserId","ownerUserId","sourceStripeEventId","stripeCheckoutSessionId","stripePaymentIntentId","stripeSubscriptionId","metadataJson","privateR2ObjectKeys","signedUrls"],"writeBoundary":"Issue #141 exposes a checkout-intent-scoped customer entitlement lookup with product, access-rule, and fulfillment status only. Issue #143 can create one-use download tokens for active file entitlements, issue #146 can stream a seeded private R2-backed fixture through Bumpgrade, issue #147 revalidates current entitlement and trusted checkout state at redemption, and issue #187 can show subscription-backed membership entitlement state after trusted Stripe Billing events. Private R2 keys, signed URLs, protected lessons, private buyer data, entitlement mutation, revocation, arbitrary asset uploads, Customer Portal actions, and live fulfillment automation remain future authenticated confirmed-write APIs."},"sandboxDownloadTokens":{"id":"sandbox-product-download-token-contract","status":"private-r2-download-delivery-ready","issue":146,"followsIssue":143,"redemptionRevalidationIssue":147,"parentIssue":16,"apiRoute":"/api/products/download-tokens","downloadRoutePrefix":"/api/products/downloads","sourceDataRoute":"/products/source-data","ttlSeconds":900,"tables":["product_download_tokens"],"privateAssetBucketBinding":"PRODUCT_ASSETS","authBoundary":"checkout-intent-and-entitlement-bearer-reference","eligibleAssetKind":"file","deliveryMode":"private-r2-fixture","privateAssetDelivery":{"r2Backed":true,"seededAssetId":"asset-launch-checklist-pdf","rawR2KeysIncluded":false,"signedUrlsIncluded":false},"redemptionRevalidation":{"entitlementStatus":"active","trustedCheckoutStatuses":["paid","completed"],"checkoutIntentLinkRequired":true,"assetScopeCheckedBeforeRead":true,"tokenConsumedAfterPrivateAssetRead":true},"redaction":{"buyerEmailIncluded":false,"buyerEmailHashIncluded":false,"rawStripeIdsIncluded":false,"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"metadataJsonIncluded":false},"writeBoundary":"Issue #146 can create short-lived download tokens for active checkout-linked file entitlements and stream a seeded private R2-backed fixture through Bumpgrade. Issue #147 revalidates current entitlement status, checkout intent linkage, trusted checkout state, and asset scope before private R2 reads or token consumption. It does not expose private R2 keys, signed object URLs, protected lessons, buyer identity, revocation, subscription access, arbitrary uploads, or live fulfillment automation."},"ownerAssetUploadIntents":{"id":"owner-private-product-asset-upload-intents","status":"owner-private-asset-upload-intents-ready","issue":151,"parentIssue":16,"apiRoute":"/api/admin/products/assets","sourceDataRoute":"/products/source-data","ownerAuthBoundary":"Better Auth owner session","confirmation":{"required":true,"text":"Create private product asset upload intent"},"idempotencyRequired":true,"staleStateCheck":{"required":true,"field":"expectedCatalogRevisionId","currentRevisionId":"product-access-revision-indie-launch-2026-05-19"},"maxPayloadBytes":65536,"tables":["product_asset_uploads"],"privateAssetBucketBinding":"PRODUCT_ASSETS","redaction":{"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"rawUploadBodyIncluded":false,"privateMetadataIncluded":false,"rawOwnerEmailIncluded":false,"buyerDataIncluded":false},"writeBoundary":"Verified owners can create small private product asset upload records after exact confirmation, idempotency, and product-catalog revision checks. The API stores the body in PRODUCT_ASSETS under a server-only object key and returns only public-safe metadata. It does not expose R2 object keys, signed URLs, upload bodies, private owner metadata, buyer data, customer delivery, protected content, revocation, or direct unauthenticated agent writes.","source":"d1","loadError":null,"counts":{"uploadRecords":1,"storedPrivateUploads":1},"latestCreatedAt":"2026-05-19T18:32:23.000Z","rawRowsIncluded":false},"revocationIntents":{"id":"product-entitlement-revocation-intent-contract","status":"owner-product-revocation-intents-ready","issue":179,"parentIssue":16,"ownerRoute":"/admin/products","publicSourceDataRoute":"/products/source-data","apiRoute":"/api/admin/products/revocation-intents","writeIssue":251,"source":"d1","loadError":null,"confirmation":{"required":true,"text":"Record product access removal intent"},"idempotencyRequired":true,"staleStateCheck":{"required":true,"field":"expectedEntitlementStatus"},"reasonCodes":["manual_review","refund_or_chargeback","customer_request","test_cleanup"],"counts":{"revocationIntents":1,"dryRunIntents":1,"ownerConfirmedIntents":0,"destructiveActionsEnabled":0,"entitlementMutationsEnabled":0},"records":[{"id":"revocation-intent-launch-download-dry-run","productId":"product-launch-checklist-download","productTitle":"Launch checklist download","entitlementTemplateId":"entitlement-template-launch-download","entitlementTemplateTitle":"Launch download entitlement","accessRuleId":"access-rule-download-after-paid-webhook","accessRuleTitle":"Grant download after paid checkout","status":"revocation_intent_ready","intentKind":"owner_confirmed_dry_run","reasonCode":null,"ownerConfirmed":false,"privateReasonRecorded":false,"revocationPolicy":"Future revocation must require owner identity, exact confirmation, current entitlement status, refund/dispute/manual reason, and customer-safe notification review before access removal.","staleStatePolicy":"Reject future destructive revocation if entitlement status, checkout state, buyer scope, or product mapping changed since the owner reviewed it.","auditCorrelationPolicy":"Future revocation rows must include owner action id, entitlement id, checkout intent id, product id, reason code, idempotency key, and redacted audit event id.","destructiveActionEnabled":false,"entitlementMutationEnabled":false,"targetEntitlementIncluded":false,"actorIdentityIncluded":false,"createdAt":"2026-05-20T01:05:56.000Z","updatedAt":"2026-05-20T01:05:56.000Z"}],"redaction":{"privateBuyerDataIncluded":false,"rawBuyerEmailIncluded":false,"actorEmailIncluded":false,"actorEmailHashIncluded":false,"rawStripeIdsIncluded":false,"targetEntitlementIdsIncluded":false,"privateReasonIncluded":false,"entitlementMutationEnabled":false,"destructiveActionEnabled":false},"privateFieldsExcluded":["buyerEmail","buyerEmailHash","actorEmail","actorEmailHash","targetEntitlementId","stripeCheckoutSessionId","stripePaymentIntentId","stripeSubscriptionId","metadataJson","privateReason","privateReasonNote"],"writeBoundary":"Issue #179 exposes non-destructive product entitlement revocation intent readiness. Issue #251 lets verified owners record non-destructive revocation intents after exact confirmation, idempotency, and a current entitlement status check. It does not revoke access, mutate entitlements, expose buyer data, change billing, issue refunds, notify customers, or authorize direct public agent revocation writes."},"protectedContent":{"id":"product-protected-content-readiness-contract","status":"protected-product-content-readiness-ready","issue":181,"parentIssue":16,"ownerRoute":"/admin/products","publicSourceDataRoute":"/products/source-data","source":"d1","loadError":null,"counts":{"protectedContentItems":2,"courseItems":1,"membershipItems":1,"deliveryEnabled":2,"protectedBodiesIncluded":0},"records":[{"id":"protected-content-launch-course-module-1","productId":"product-launch-course-lite","productTitle":"Launch course lite","assetId":"asset-launch-course-lessons","assetTitle":"Launch course lessons","entitlementTemplateId":"entitlement-template-launch-course","entitlementTemplateTitle":"Launch course entitlement","status":"protected_content_ready","contentKind":"course_module","title":"Launch course module readiness","publicSummary":"Public-safe metadata for the first protected course module.","accessPolicy":"Future delivery must require an active course entitlement, current trusted checkout state, and a fresh access check before any lesson body, video, transcript, or progress row is returned.","privateContentBoundary":"Lesson body, video URL, transcript body, progress state, buyer identity, private R2 object keys, and signed URLs are excluded from this readiness record.","deliveryEnabled":true,"protectedBodyIncluded":false,"updatedAt":"2026-05-20T02:21:17.000Z"},{"id":"protected-content-launch-member-area","productId":"product-launch-membership","productTitle":"Launch membership","assetId":"asset-launch-member-area","assetTitle":"Launch member area","entitlementTemplateId":"entitlement-template-launch-membership","entitlementTemplateTitle":"Launch membership entitlement","status":"protected_content_ready","contentKind":"member_area","title":"Launch member area readiness","publicSummary":"Public-safe metadata for a future protected member area.","accessPolicy":"Future delivery must require active subscription-backed membership entitlement, stale-state checks, and redacted audit evidence before member posts or files are returned.","privateContentBoundary":"Member post bodies, private files, community data, subscription identifiers, buyer identity, private R2 object keys, and signed URLs are excluded from this readiness record.","deliveryEnabled":true,"protectedBodyIncluded":false,"updatedAt":"2026-05-20T02:21:17.000Z"}],"redaction":{"privateContentBodiesIncluded":false,"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"buyerDataIncluded":false,"progressDataIncluded":false,"deliveryEnabled":false},"delivery":{"id":"product-protected-content-delivery-contract","status":"protected-product-content-delivery-ready","issue":185,"followsIssue":181,"parentIssue":16,"apiRoute":"/api/products/protected-content","sourceDataRoute":"/products/source-data","authBoundary":"checkout-intent-and-entitlement-bearer-reference","lookupInputs":["checkoutIntentId","entitlementId","protectedContentId"],"eligibleContentKinds":["course_module","member_area"],"deliveryMode":"seeded-protected-fixture","trustedCheckoutStatuses":["paid","completed"],"redaction":{"buyerEmailIncluded":false,"buyerEmailHashIncluded":false,"rawStripeIdsIncluded":false,"sourceStripeEventIdsIncluded":false,"rawR2KeysIncluded":false,"signedUrlsIncluded":false,"metadataJsonIncluded":false,"protectedBodyIncludedInSourceData":false,"progressDataIncluded":false},"writeBoundary":"Issue #185 can return seeded protected course/member fixture bodies only for an active checkout-linked entitlement whose product/template scope matches the protected content section and whose checkout state is currently paid or completed. It does not expose buyer identity, raw Stripe IDs, webhook IDs, private R2 keys, signed URLs, metadata JSON, progress rows, arbitrary uploaded content, live fulfillment automation, or direct unauthenticated agent writes."},"privateFieldsExcluded":["lessonBody","videoUrl","transcriptBody","memberPostBody","progressState","privateR2ObjectKeys","signedUrls","buyerEmail","buyerEmailHash"],"writeBoundary":"Issue #181 exposes protected product content readiness metadata only. Issue #185 can return seeded protected fixture bodies only through checkout-intent and entitlement-scoped delivery checks. It does not deliver videos, transcripts, real member posts, progress records, signed URLs, private R2 objects, arbitrary uploaded content, or live fulfillment automation to customers or agents."}}