Skip to content

Latest commit

 

History

History
2151 lines (1429 loc) · 63.9 KB

implementation.md

File metadata and controls

2151 lines (1429 loc) · 63.9 KB

ReLoop Rewards - End-to-End Implementation Plan

ReLoop Rewards is an open-source recycling-incentive platform for recording verified collection events and distributing immediate RUSD micro-rewards through the Fiber Network. A recycler or sponsor defines a bounded campaign, an authorized operator verifies collection at a known site, and a participant receives a reward after the event passes the campaign rules.

The first beta is intentionally narrow: one partner, one collection site, one material type, 50 invited participants, and at least 200 accepted collection events. It is not a national recycling marketplace, a new token, a carbon-credit registry, an automated reverse-vending machine, or a system that claims software can prove physical recycling without an operator and partner process.


Implementation Objective

The implementation must prove the following product claim:

A sponsor can publish bounded collection rules, an authorized operator can verify a participant event, the system can reject duplicate and ineligible claims, an accepted event can create exactly one RUSD Fiber reward, and the resulting recovery and payment record can be audited against a CKB commitment.

The beta is complete only when it demonstrates:

  • campaign creation with material, site, reward, limits, and budget rules;
  • participant onboarding with a QR identity;
  • operator authorization for the selected collection site;
  • item-count and weight-based event recording;
  • optional evidence photo capture with explicit consent;
  • deterministic duplicate, quota, campaign, and operator checks;
  • exactly-once payout reservation for every accepted event;
  • real RUSD testnet payment through a pinned Fiber integration;
  • participant payout status and payment proof;
  • sponsor recovery, rejection, and payout dashboards;
  • privacy-filtered audit export;
  • CKB commitment for campaign rules and daily collection records;
  • automated tests, deployment documentation, pilot evidence, and reconciliation reporting.

Product Decisions Locked for the Beta

Decision Beta choice Reason
Initial pilot One recycling partner and one collection site Keeps physical verification and support manageable
Material One selected material, for example PET bottles Makes reward and reconciliation rules unambiguous
Participants 50 invited participants Allows controlled identity and abuse monitoring
Target activity At least 200 accepted collection events Produces enough evidence for payout and reconciliation testing
Operator model Authorized site operator records and approves events Software does not pretend to verify physical activity alone
Participant identity QR-based participant identifier Works on low-cost phones without requiring a new wallet
Reward asset Testnet RUSD Stable unit for understandable pilot accounting
Settlement Fiber testnet payment after operator approval Demonstrates immediate micro-reward behavior
Campaign scope One site, one material, fixed campaign window Prevents unbounded claims in the beta
Evidence photo Optional, consent-based, private by default Supports review without publishing personal imagery
On-chain data Public hashes and campaign metadata only Keeps personal data and photos off-chain
Mainnet Out of scope Requires separate custody, legal, liquidity, and operational review
New asset Out of scope RUSD is sufficient for the proof
Carbon credits Out of scope Collection records are not environmental certificates
Automation Operator-assisted verification No reverse-vending machine integration is required

How It Works

Sponsor creates campaign rules and budget
    |
Operator is assigned to the campaign site
    |
Participant claims an invite and receives a QR identity
    |
Participant presents QR code at the collection site
    |
Operator records material, count or weight, time, station, and optional photo
    |
Validation checks campaign rules, operator authority, limits, and duplicates
    |
Accepted event reserves one payout exactly once
    |
Fiber worker validates invoice and pays RUSD
    |
Participant sees payment status and proof
    |
Sponsor sees recovered totals, rejected events, and payout totals
    |
Daily accepted records and payout summary are committed to CKB
    |
Sponsor downloads a privacy-filtered reconciliation report

Trust, Privacy, and Custody Boundary

The public beta must describe its trust model directly.

Physical Verification

  • The operator is responsible for accepting or rejecting the physical collection event.
  • The platform records who approved the event, where it was recorded, and when it was recorded.
  • The platform can detect duplicate, over-limit, and inconsistent claims but cannot prove that every physical item existed.
  • Sponsor and partner procedures remain part of the trust model.
  • A photo is supporting evidence, not an automatic truth oracle.

Payment Custody

  • A server-side Fiber payer is used for the sponsored testnet pilot.
  • Browser and participant clients never receive payer credentials or private keys.
  • The worker reserves a payout before calling a spending RPC.
  • Ambiguous payment results are reconciled before retrying.
  • All reward amounts use integer base units, never floating-point values.
  • Testnet payments have no mainnet monetary value.

Participant Privacy

  • Participant identity data is separated from public recovery exports.
  • Public exports contain participant pseudonyms or stable redacted IDs, not names or phone numbers.
  • Exact home locations and unrelated movement data are never collected.
  • Photos are private review evidence and are not included in public CKB commitments.
  • Photo retention and deletion rules are visible to participants and operators.
  • Logs redact QR secrets, payment credentials, private endpoints, and evidence URLs.

CKB Boundary

  • CKB stores campaign and collection-record commitments, not raw personal data.
  • The committed content is canonicalized before hashing.
  • A commitment proves that a published record set matched a hash at a given time.
  • A commitment does not prove that a physical event was honest or that a photo is authentic.

Architecture Overview

Participant Web App / Mobile Web
  - invite claim
  - QR identity
  - campaign instructions
  - event history
  - payout status
          |
          | HTTPS
          v
Application API
  - authentication and roles
  - campaign rules
  - participant profiles
  - operator event intake
  - validation decisions
  - payout records
  - exports and audit queries
          |
          +--------------------+
          |                    |
          v                    v
PostgreSQL                Redis / Worker Queue
  - users                     - payout jobs
  - campaigns                 - commitment jobs
  - events                    - export jobs
  - payouts                   - cleanup jobs
  - commitments               - reconciliation jobs
          |                    |
          |                    v
          |              Fiber Settlement Service
          |                - invoice validation
          |                - send_payment
          |                - payment lookup
          |                - idempotency
          |
          v
Sponsor and Operator Web App
  - campaign management
  - event review
  - payout monitoring
  - reconciliation reports

CKB Commitment Worker
  - campaign rules hash
  - daily recovery-record root
  - payout summary hash

Architectural Rules

  • Browser code never receives Fiber payer credentials.
  • Only the settlement worker may call Fiber spending methods.
  • Every event has a stable idempotency key.
  • An accepted event can have at most one payout reservation.
  • A payout is reserved before any payment request is sent.
  • An ambiguous payment is not treated as failed until reconciled.
  • Campaign rules become immutable after activation.
  • Public exports are generated from accepted records and explicit privacy transforms.
  • CKB commitment data contains hashes and public metadata only.
  • Operator authorization is checked on the server, not only in the UI.
  • All state transitions are recorded as audit events.

Target Tech Stack

Layer Technology
Participant and sponsor app Next.js App Router + TypeScript
Styling Tailwind CSS or the selected project design system
API Fastify or Next.js route handlers with service boundaries
Database PostgreSQL + Prisma
Jobs Redis + BullMQ
Validation Zod schemas and deterministic validation services
Fiber integration Versioned JSON-RPC adapter pinned to a tested FNN release
CKB integration CCC transaction builder and cell reader
QR codes Standard QR encoder and scanner library
Object storage S3-compatible private bucket for evidence photos
Tests Vitest, integration tests, and Playwright
Local deployment Docker Compose
CI GitHub Actions

The exact Fiber node version, RUSD asset ID, CKB network, storage provider, and deployment settings must be pinned during the validation work. No production Compose file may use latest.


Repository Structure

ckb-reloop-rewards/
  implementation.md
  README.md
  .env.example
  package.json
  pnpm-workspace.yaml
  docker-compose.yml
  apps/
    web/
      app/
        participant/
        operator/
        sponsor/
        admin/
        api/
      components/
      lib/
      tests/
    worker/
      src/
        payouts/
        commitments/
        exports/
        cleanup/
        reconciliation/
    api/
      src/
        auth/
        campaigns/
        participants/
        operators/
        events/
        validation/
        payouts/
        exports/
        commitments/
        audit/
  packages/
    contracts/
      src/
        campaign.ts
        participant.ts
        collection-event.ts
        payout.ts
        commitment.ts
        states.ts
    database/
      prisma/
        schema.prisma
      src/
    validation-engine/
      src/
        rules.ts
        duplicate.ts
        quotas.ts
        decisions.ts
    fiber-rpc/
      src/
        adapter.ts
        transport.ts
        invoices.ts
        payments.ts
        reconciliation.ts
    ckb-commitment/
      src/
        canonical.ts
        merkle.ts
        transaction.ts
        verify.ts
    qr-identity/
      src/
        payload.ts
        signing.ts
        verification.ts
    export/
      src/
        recovery.ts
        payments.ts
        reconciliation.ts
        redaction.ts
    testkit/
      src/
        fake-fiber.ts
        fake-events.ts
        fixtures.ts
  infrastructure/
    fiber/
      payer/
      receiver/
    postgres/
    redis/
    storage/
    ckb/
  scripts/
    seed-pilot.ts
    fiber-smoke-test.ts
    commit-campaign.ts
    commit-daily-records.ts
    verify-commitment.ts
    reconcile-pilot.ts
  docs/
    architecture.md
    privacy.md
    data-retention.md
    validation-policy.md
    fiber-compatibility.md
    deployment.md
    pilot-runbook.md
    threat-model.md
    partner-guide.md

Core Domain Model

User

  • id
  • role: participant, operator, sponsor, reviewer, admin
  • email or verified contact reference where required
  • status: invited, active, suspended, deleted
  • createdAt
  • updatedAt

SponsorOrganization

  • id
  • name
  • partnerReference
  • status
  • createdAt
  • updatedAt

CollectionSite

  • id
  • organizationId
  • name
  • publicAddressLabel
  • timezone
  • operatorInstructions
  • status

Campaign

  • id
  • organizationId
  • siteId
  • name
  • materialCode
  • materialLabel
  • measurementMode: count or weight
  • rewardPerUnit
  • weightUnit when applicable
  • minimumUnit
  • maximumUnit
  • participantLimit
  • eventLimit
  • budgetBaseUnits
  • startAt
  • endAt
  • status
  • rulesVersion
  • rulesHash
  • createdBy
  • activatedAt
  • closedAt

ParticipantProfile

  • id
  • userId
  • publicParticipantCode
  • qrSecretHash
  • payoutReceiverReference
  • consentVersion
  • consentAcceptedAt
  • status

OperatorAssignment

  • id
  • campaignId
  • siteId
  • operatorUserId
  • status
  • validFrom
  • validUntil

CollectionEvent

  • id
  • campaignId
  • siteId
  • participantId
  • operatorUserId
  • eventKey
  • materialCode
  • quantity
  • measurementUnit
  • recordedAt
  • stationReference
  • evidenceObjectKey
  • evidenceConsent
  • status: received, accepted, rejected, needs_review, cancelled
  • decisionReasonCode
  • acceptedAt
  • rejectedAt
  • createdAt

ValidationFinding

  • id
  • eventId
  • ruleCode
  • severity
  • detailsRedacted
  • createdAt

Payout

  • id
  • eventId
  • participantId
  • amountBaseUnits
  • assetId
  • idempotencyKey
  • status: reserved, invoice_created, submitted, confirming, paid, failed, ambiguous, cancelled
  • invoiceReference
  • paymentHash
  • failureCode
  • createdAt
  • updatedAt

FiberPayment

  • id
  • payoutId
  • invoiceReference
  • paymentHash
  • senderNodeReference
  • receiverReference
  • amountBaseUnits
  • assetId
  • status
  • rawResponseRedacted
  • confirmedAt

Commitment

  • id
  • kind: campaign_rules, daily_events, payout_summary
  • campaignId
  • periodStart
  • periodEnd
  • rootHash
  • recordCount
  • ckbTxHash
  • status: pending, submitted, confirmed, failed
  • createdAt

AuditEvent

  • id
  • actorUserId
  • entityType
  • entityId
  • action
  • beforeHash
  • afterHash
  • metadataRedacted
  • createdAt

Money Rules

  • Store RUSD amounts as decimal strings representing base units.
  • Never use JavaScript floating-point arithmetic for rewards or budgets.
  • Validate that the reward is positive and within campaign limits.
  • Calculate the event reward from canonical campaign rules, not from a client-submitted amount.
  • Reserve campaign budget before sending a payment.
  • Do not release a reserved amount until the payout is terminal.
  • Record the exact asset ID on every payout and payment.
  • Reject payments whose invoice amount, asset, receiver, or campaign ID differs from the reservation.
  • Record fees separately from participant reward amounts.
  • Report paid, failed, ambiguous, and remaining budget totals independently.

Campaign State Machine

draft -> review
review -> scheduled
review -> draft
scheduled -> active
scheduled -> cancelled
active -> paused
active -> closed
paused -> active
paused -> closed
closed -> exported
exported -> archived

State Invariants

  • A campaign cannot activate without a valid site, material, reward rule, budget, and operator assignment.
  • An active campaign has an immutable rules hash.
  • A paused campaign accepts no new accepted events.
  • A closed campaign accepts no new event records except administrative reconciliation notes.
  • A campaign cannot exceed its participant limit, event limit, or budget cap.
  • A campaign cannot be archived until its final export and reconciliation report exist.

Collection Event State Machine

received -> validating
validating -> accepted
validating -> rejected
validating -> needs_review
needs_review -> accepted
needs_review -> rejected
accepted -> payout_reserved
payout_reserved -> paid
payout_reserved -> payout_failed
accepted -> cancelled

Event Invariants

  • Only an assigned operator can create or approve an event.
  • The event material must match the campaign material.
  • The event site must match the campaign site.
  • The event timestamp must be inside the campaign window.
  • One event key can create only one event.
  • One accepted event can create only one payout.
  • A rejected event cannot create a payout.
  • A payout failure does not silently change the event back to accepted without an audit record.

Validation Contract

Required Checks

  1. Campaign exists and is active.
  2. Campaign has not exceeded its end time.
  3. Operator assignment is valid for the campaign and site.
  4. Participant is invited, active, and eligible.
  5. Participant consent version matches the campaign requirement.
  6. QR payload is authentic, unexpired, and belongs to the participant.
  7. Material code matches the campaign.
  8. Quantity is a valid positive integer or bounded decimal string.
  9. Quantity is within the configured per-event bounds.
  10. Event timestamp is within the allowed clock skew.
  11. Event key has not already been used.
  12. Participant event count has not reached the participant limit.
  13. Campaign event count has not reached the event limit.
  14. Remaining budget covers the calculated reward.
  15. Evidence photo, when supplied, meets type, size, and consent rules.

Validation Outcomes

  • accepted: all required checks passed.
  • rejected: a deterministic rule failed and no manual review can change the result.
  • needs_review: an operator or reviewer must inspect the event.
  • invalid_request: the API request cannot be parsed or authenticated.

The validation engine returns stable rule codes without exposing private participant data.


Phase Summary

Phase Scope Exit evidence
0 Pilot decisions and feasibility Locked rules and written limitations
1 Repository and tooling foundation Workspace builds and CI runs
2 Configuration and secrets boundary Validated environment contract
3 Shared contracts and money types Contract tests pass
4 Database schema and migrations Fresh database migration succeeds
5 Authentication and roles Role access tests pass
6 Sponsor organization and site setup Site and operator assignment work
7 Campaign creation Draft campaign validates
8 Campaign canonicalization Stable rules hash is produced
9 Campaign review and activation Immutable active campaign exists
10 Participant invitations Invite claim works once
11 QR identity Authentic QR payloads can be issued and verified
12 Participant consent Consent is versioned and auditable
13 Operator collection screen Operator can record a draft event
14 Event intake API Valid event request is persisted
15 Deterministic validation Positive and negative rules pass
16 Manual review Review decisions are auditable
17 Exactly-once event acceptance Duplicate event race is safe
18 Payout reservation One accepted event reserves one payout
19 Fiber adapter Invoice and payment contracts are tested
20 Fiber testnet payment Confirmed RUSD payment exists
21 Payment reconciliation Ambiguous payments are recoverable
22 Participant payout history Status and proof are visible
23 Sponsor recovery dashboard Totals agree with accepted events
24 Privacy and evidence storage Photos are private and governed
25 Export package CSV, audit, and reconciliation exports verify
26 CKB campaign commitment Campaign rules commitment is confirmed
27 Daily collection commitment Daily root and proof verify
28 Payout summary commitment Payment summary commitment verifies
29 Admin safety controls Holds, limits, and emergency stop work
30 Notifications and operations User-facing failure handling works
31 Unit and integration tests Core test suite passes
32 Concurrency and security tests Race and abuse tests pass
33 Browser and accessibility tests Critical workflows pass in browser
34 Local deployment Docker Compose starts from empty state
35 Testnet deployment Public beta environment is reproducible
36 Pilot preparation Partner and participant runbooks are ready
37 Pilot execution 200 accepted events and payment evidence exist
38 Reconciliation and reporting Physical and digital totals reconcile
39 Release and handover Public repository and maintenance package are complete

Phase 0 - Pilot Decisions and Feasibility

Step 0.1 - Select the Partner and Site

Tasks:

  • Select one recycler, sponsor, university, community center, or event partner.
  • Confirm the exact collection site and operating hours.
  • Identify the person responsible for physical acceptance.
  • Confirm how material will be stored and counted after collection.
  • Record the material type and why it is measurable at the site.

Audit:

  • Partner, site, operator, material, and pilot dates are written in docs/product-decisions.md.
  • The site can support at least 200 events without changing the rules.

Step 0.2 - Define the Reward Rule

Tasks:

  • Choose count or weight as the primary measurement.
  • Define the reward per item or unit weight.
  • Define minimum and maximum event quantity.
  • Define participant and campaign limits.
  • Define the total campaign budget.
  • Decide how rounding works for weight-based rewards.

Audit:

  • A sample rule can be calculated without floating-point arithmetic.
  • The participant-facing rule and sponsor-facing rule are identical.

Step 0.3 - Verify the RUSD Testnet Path

Tasks:

  • Select and pin the Fiber testnet node version.
  • Confirm the RUSD asset ID and decimal convention.
  • Identify the payer node and receiver setup.
  • Send a manual testnet payment.
  • Record invoice, payment, confirmation, and failure behavior.

Audit:

  • docs/fiber-compatibility.md contains the tested RPC methods and versions.
  • A manual payment hash is recorded without storing secrets in the repository.

Step 0.4 - Verify the CKB Commitment Path

Tasks:

  • Select the CKB testnet network and RPC endpoint.
  • Confirm the CCC version and known scripts needed for the commitment.
  • Choose the commitment cell format.
  • Send a minimal test commitment.
  • Verify the commitment from a second read path.

Audit:

  • The commitment payload contains no participant names, QR secrets, photos, or payment credentials.
  • The test transaction and explorer link are recorded in private pilot notes.

Step 0.5 - Lock the Beta Limitations

Tasks:

  • Write the non-goals into the product decisions document.
  • Define what the operator is trusted to do.
  • Define what the software can detect and what it cannot prove.
  • Define testnet-only language for every payment screen.

Exit Criteria:

  • Partner, site, material, reward, budget, testnet services, and trust boundaries are approved.

Phase 1 - Repository and Tooling Foundation

Step 1.1 - Create the Workspace

Tasks:

  • Create the repository and package manager workspace.
  • Add the web, API, worker, and shared package directories.
  • Add formatting, linting, type checking, and test scripts.
  • Add a root README with local setup instructions.

Step 1.2 - Create the Web Application

Tasks:

  • Create the participant, operator, sponsor, and admin route groups.
  • Add a shared layout and error boundary.
  • Add loading, empty, unauthorized, and failure states.
  • Add the initial design tokens and responsive shell.

Step 1.3 - Create the API and Worker Applications

Tasks:

  • Create the API process and health route.
  • Create the worker process and health check.
  • Add typed service boundaries between routes, domain logic, and adapters.
  • Add structured redacted logging.

Step 1.4 - Add CI Baseline

Tasks:

  • Run type checking, linting, unit tests, and build in CI.
  • Add a database service for integration tests.
  • Add dependency lockfile checks.
  • Add a diff check that rejects committed secrets.

Exit Criteria:

  • A clean checkout installs, checks, tests, and builds without manual edits.

Phase 2 - Configuration and Secrets Boundary

Step 2.1 - Define Environment Variables

Add typed configuration for:

  • database URL;
  • Redis URL;
  • session secret;
  • CKB network and RPC URL;
  • CCC configuration;
  • Fiber RPC URL and node version;
  • RUSD asset ID;
  • payer node credentials;
  • private evidence storage;
  • application origin;
  • retention durations.

Step 2.2 - Validate Configuration at Startup

Tasks:

  • Reject missing required values.
  • Reject malformed URLs and asset IDs.
  • Reject production mode with testnet-disabled safeguards missing.
  • Print only safe configuration names and versions.

Step 2.3 - Document Secret Handling

Tasks:

  • Add .env.example with placeholders only.
  • Document local secret injection.
  • Document deployment secret configuration.
  • Add a secret scanning check.

Exit Criteria:

  • No private key, payer password, QR secret, or storage credential appears in source, tests, logs, or example files.

Phase 3 - Shared Contracts and Money Types

Step 3.1 - Define Enumerations and Statuses

Implement shared types for roles, campaign states, event states, payout states, commitment states, units, and validation outcomes.

Step 3.2 - Implement Integer Money Utilities

Tasks:

  • Parse base-unit strings.
  • Add and subtract without floating point.
  • Reject negative and malformed values.
  • Compare values safely.
  • Format values for the UI without changing stored precision.

Step 3.3 - Add Zod Request Schemas

Define schemas for campaign rules, participant claims, QR payloads, collection events, review decisions, payout requests, exports, and commitment records.

Step 3.4 - Add Contract Fixtures

Create valid and invalid fixtures for every shared contract. Keep fixtures deterministic so they can be used by API, worker, and browser tests.

Exit Criteria:

  • Every API boundary rejects malformed input before domain services run.
  • Money and status types are imported from one shared package.

Phase 4 - Database Schema and Migrations

Step 4.1 - Create Identity Tables

Implement User, ParticipantProfile, SponsorOrganization, CollectionSite, and OperatorAssignment.

Step 4.2 - Create Campaign Tables

Implement Campaign, campaign rule versions, activation records, and budget reservations.

Step 4.3 - Create Event Tables

Implement CollectionEvent, ValidationFinding, review decisions, and event evidence references.

Step 4.4 - Create Settlement Tables

Implement Payout, FiberPayment, invoice attempts, reconciliation attempts, and idempotency keys.

Step 4.5 - Create Audit and Commitment Tables

Implement AuditEvent, Commitment, commitment records, and export manifests.

Step 4.6 - Add Constraints and Indexes

Add database enforcement for:

  • unique event keys;
  • unique payout per event;
  • unique payout idempotency key;
  • unique operator assignment where required;
  • valid state values;
  • nonnegative amounts;
  • campaign and site lookup indexes;
  • payout and commitment reconciliation indexes.

Step 4.7 - Test Fresh Migrations

Tasks:

  • Run migrations against an empty database.
  • Seed a minimal pilot.
  • Roll back only in disposable test environments.
  • Test transaction boundaries for event and payout creation.

Exit Criteria:

  • A fresh database can run the application and seed fixtures with no manual SQL.

Phase 5 - Authentication and Role Authorization

Step 5.1 - Implement Session Authentication

Tasks:

  • Choose the beta authentication method.
  • Create secure sessions with expiration and rotation.
  • Add logout and session invalidation.
  • Avoid placing private participant or payer data in browser-readable tokens.

Step 5.2 - Implement Role Guards

Implement server-side guards for participant, operator, sponsor, reviewer, and admin actions.

Step 5.3 - Implement Organization and Site Scope

Ensure a sponsor can access only its organization, an operator only assigned sites, and a participant only its own records.

Step 5.4 - Audit Authorization Failures

Add tests for anonymous access, wrong role, wrong organization, wrong campaign, and suspended users.

Exit Criteria:

  • Every protected route has a server-side authorization test.

Phase 6 - Sponsor Organization and Site Setup

Step 6.1 - Create Sponsor Organization

Tasks:

  • Create organization record.
  • Add sponsor administrators.
  • Store partner reference without exposing private agreements.
  • Add organization status controls.

Step 6.2 - Create Collection Site

Tasks:

  • Store site label, timezone, operating hours, and instructions.
  • Avoid collecting participant residence or unrelated location data.
  • Add active and inactive states.

Step 6.3 - Assign Operators

Tasks:

  • Assign an operator to a site and campaign.
  • Add validity dates.
  • Revoke assignment without deleting historical event records.

Step 6.4 - Build Site Setup UI

Create sponsor and admin screens for site details and operator assignments with clear active-state indicators.

Exit Criteria:

  • A campaign cannot use a site without an active operator assignment.

Phase 7 - Campaign Creation and Rules

Step 7.1 - Build Campaign Draft Form

Collect:

  • campaign name;
  • material;
  • site;
  • count or weight mode;
  • reward rule;
  • event bounds;
  • participant and event limits;
  • budget;
  • start and end time;
  • consent and retention version.

Step 7.2 - Validate Campaign Rules

Reject missing material, invalid time windows, zero rewards, invalid bounds, insufficient budget, and unassigned sites.

Step 7.3 - Show Rule Preview

Display an example event and calculated reward before the campaign is submitted for review.

Step 7.4 - Add Campaign Draft API

Implement create, update, read, and list operations with organization scope and audit events.

Exit Criteria:

  • A sponsor can create a valid draft and receives stable validation errors for invalid rules.

Phase 8 - Campaign Canonicalization and Rules Hash

Step 8.1 - Define Canonical Rules Format

Sort object keys, normalize timestamps, normalize material codes, normalize decimal strings, and omit non-rule metadata.

Step 8.2 - Hash Canonical Rules

Create a deterministic hash from the canonical rule document.

Step 8.3 - Compare Rule Versions

Show changed rules between versions before activation. Never silently mutate an activated version.

Step 8.4 - Add Canonicalization Tests

Test key ordering, whitespace, timestamp representation, decimal representation, and omitted metadata.

Exit Criteria:

  • Identical rules always produce the same hash across processes.
  • A meaningful rule change always produces a different hash.

Phase 9 - Campaign Review and Activation

Step 9.1 - Build Review Queue

Show draft rules, sponsor, site, operator, budget, consent version, and rules hash.

Step 9.2 - Implement Review Decision

Allow an authorized reviewer to approve or return a campaign with a reason. Record before and after hashes.

Step 9.3 - Implement Activation Preconditions

Require a valid campaign, active site, operator assignment, reward configuration, budget, participant limit, and rules hash.

Step 9.4 - Lock Activated Rules

Prevent edits to any value that affects eligibility, reward, limits, or commitment content. Changes require a new campaign or version.

Exit Criteria:

  • An active campaign has a stable rules hash and cannot be changed through API or UI shortcuts.

Phase 10 - Participant Invitations and Onboarding

Step 10.1 - Generate Invites

Create single-use or bounded invite codes linked to a campaign and expiry time.

Step 10.2 - Claim Invite

Tasks:

  • Validate invite status and expiry.
  • Create or link participant account.
  • Prevent a code from being claimed twice.
  • Record claim audit event.

Step 10.3 - Show Campaign Briefing

Display site, material, reward, limits, campaign dates, purpose, privacy policy, and testnet payment disclosure.

Step 10.4 - Handle Suspension

Prevent suspended participants from creating new events while preserving their history and payout records.

Exit Criteria:

  • A participant can claim one campaign invite and see only the campaign information relevant to them.

Phase 11 - QR Identity

Step 11.1 - Define QR Payload

The payload should contain a short participant reference, campaign scope where appropriate, expiry, nonce, and an integrity mechanism. It must not contain a private secret or unnecessary personal data.

Step 11.2 - Issue QR Code

Create a participant QR screen with regeneration and revocation controls.

Step 11.3 - Verify QR Payload

Verify authenticity, expiry, campaign scope, participant status, and replay protection on the server.

Step 11.4 - Support Operator Scanning

Add camera scanning and manual short-code fallback for supported devices and controlled pilot recovery.

Step 11.5 - Test QR Abuse Cases

Test expired, malformed, copied, wrong-campaign, revoked, replayed, and suspended QR payloads.

Exit Criteria:

  • An operator can identify an eligible participant without seeing unnecessary personal information.

Phase 12 - Consent and Data Retention

Step 12.1 - Define Consent Version

Create a versioned consent document covering purpose, requested event data, photos, retention, sponsor access, and payment disclosure.

Step 12.2 - Capture Consent

Require participant acceptance before event collection. Store version, timestamp, and policy hash.

Step 12.3 - Handle Withdrawal

Prevent new submissions after withdrawal and document how retained financial and audit records are handled.

Step 12.4 - Implement Retention Jobs

Delete or anonymize expired photos and private raw evidence without deleting the minimum records needed for payment and audit obligations.

Exit Criteria:

  • Consent is required by the API, not only by the participant UI.

Phase 13 - Operator Collection Workflow

Step 13.1 - Build Operator Dashboard

Show assigned campaigns, site, operating window, material, active limits, and recent events.

Step 13.2 - Start Collection Event

Require QR identity, selected campaign, material confirmation, and measurement mode.

Step 13.3 - Record Count or Weight

Validate the displayed unit, precision, minimum, and maximum before submission. Provide a clear confirmation step.

Step 13.4 - Capture Optional Evidence

Allow an optional photo only after showing consent and storage behavior. Store the photo privately.

Step 13.5 - Preview the Event

Show participant pseudonym, material, quantity, reward estimate, site, operator, and timestamp before final approval.

Exit Criteria:

  • Operator can record a complete event without editing a campaign rule or participant payout amount.

Phase 14 - Event Intake API

Step 14.1 - Define Idempotent Event Request

Require campaign ID, participant reference, QR proof, material code, quantity, unit, client event key, timestamp, and evidence reference where applicable.

Step 14.2 - Authenticate the Operator

Check role, assignment, site, and campaign state before accepting the request.

Step 14.3 - Persist Received Event

Create the event in received state inside a database transaction. Do not mark it accepted in the route handler.

Step 14.4 - Enqueue Validation

Publish one validation job keyed by event ID and return a status response that the UI can poll.

Step 14.5 - Handle Retries

Repeated requests with the same event key return the existing event and never create a second event.

Exit Criteria:

  • Intake is authenticated, idempotent, and does not bypass the validation engine.

Phase 15 - Deterministic Validation Engine

Step 15.1 - Validate Campaign State

Reject inactive, expired, paused, cancelled, or closed campaigns.

Step 15.2 - Validate Operator Authority

Reject operators without current assignment to the campaign site.

Step 15.3 - Validate Participant Eligibility

Reject unknown, suspended, withdrawn, or over-limit participants.

Step 15.4 - Validate Material and Quantity

Reject wrong material, invalid units, zero values, negative values, excessive precision, and out-of-range quantities.

Step 15.5 - Validate Time and Site

Reject events outside campaign dates, outside site hours, or outside the accepted clock-skew window.

Step 15.6 - Validate Duplicate and Quota Rules

Check event key, recent participant events, campaign event cap, participant cap, and remaining budget.

Step 15.7 - Calculate Reward

Calculate the reward only from immutable campaign rules and canonical quantity. Store the calculation inputs and rule version.

Step 15.8 - Store Findings

Record stable rule codes and redacted details. Do not store raw secrets in findings or logs.

Exit Criteria:

  • The same input and campaign version always produce the same decision and reward.

Phase 16 - Manual Review Workflow

Step 16.1 - Define Review Triggers

Route events to review for configured anomaly conditions such as unusual quantity, evidence mismatch, or operational exception.

Step 16.2 - Build Review Queue

Show only information needed to decide the event. Redact private data by default.

Step 16.3 - Approve or Reject

Require a reviewer reason code and record the reviewer, timestamp, prior status, and new status.

Step 16.4 - Prevent Unauthorized Overrides

Do not let a reviewer change campaign reward, participant identity, event quantity, or payment amount during review.

Exit Criteria:

  • Every manual decision is auditable and cannot create a payout without a valid accepted event.

Phase 17 - Exactly-Once Acceptance and Budget Reservation

Step 17.1 - Add Event Uniqueness Constraints

Enforce unique event keys and prevent concurrent acceptance of the same event.

Step 17.2 - Reserve Event Budget

Within one transaction, verify remaining budget and reserve the calculated reward for the accepted event.

Step 17.3 - Make Acceptance Idempotent

Retries return the original decision and reservation instead of creating a new record.

Step 17.4 - Test Concurrent Submissions

Run parallel requests for the same participant, event key, campaign limit, and final budget unit.

Exit Criteria:

  • No race can create two accepted records or reserve more than the campaign budget.

Phase 18 - Payout Reservation

Step 18.1 - Create Payout Record

Create one payout for one accepted event with amount, asset, participant receiver, campaign, and idempotency key.

Step 18.2 - Validate Receiver Reference

Require a participant receiver that is present, approved for the pilot, and not changed after reservation without a controlled reauthorization.

Step 18.3 - Queue Settlement

Enqueue the payout using a stable job key. Do not call Fiber from the event request.

Step 18.4 - Add Payout State Rules

Allow only valid transitions between reserved, invoice created, submitted, confirming, paid, failed, ambiguous, and cancelled.

Exit Criteria:

  • Every accepted event has at most one payout row and every payout row points to one event.

Phase 19 - Fiber RPC Adapter

Step 19.1 - Pin the RPC Contract

Document the tested node version and methods for invoice creation, payment submission, payment lookup, and invoice lookup.

Step 19.2 - Implement Transport

Add timeouts, request IDs, redacted errors, response schema validation, and bounded retries for safe read operations.

Step 19.3 - Implement Invoice Validation

Validate receiver, amount, asset, expiry, description, and campaign reference before payment.

Step 19.4 - Implement Payment Submission

Allow only the settlement worker to submit a payment. Attach payout idempotency metadata where supported.

Step 19.5 - Implement Payment Lookup

Normalize payment states from the pinned node version into the internal state model.

Exit Criteria:

  • Fake-node tests cover success, rejection, timeout, malformed response, duplicate request, and unknown status.

Phase 20 - Fiber Testnet Settlement

Step 20.1 - Configure Sponsored Payer

Document funding, node health, asset balance, receiver setup, and maximum pilot exposure.

Step 20.2 - Create and Validate Invoice

Generate a receiver invoice from the approved participant receiver reference and compare it to the reserved payout.

Step 20.3 - Submit Payment

Submit the payment once and record the payment hash or terminal rejection.

Step 20.4 - Wait for Confirmation

Poll according to the pinned node behavior. Do not mark a payout paid from a submission response alone when confirmation is required.

Step 20.5 - Expose Participant Status

Show pending, paid, failed, and needs-reconciliation states without exposing payer credentials or internal RPC responses.

Exit Criteria:

  • At least one confirmed RUSD testnet payment is linked to an accepted event and visible in the audit report.

Phase 21 - Payment Reconciliation and Failure Handling

Step 21.1 - Classify Failures

Separate validation failure, invoice failure, transport failure, rejected payment, timeout, and ambiguous payment.

Step 21.2 - Reconcile Ambiguous Payments

Search by idempotency reference, invoice, and payment hash before retrying any uncertain request.

Step 21.3 - Quarantine Unknown Payments

Create an operator-visible reconciliation record when a payment cannot be matched safely.

Step 21.4 - Prevent Duplicate Retry

Do not submit another payment while a prior payment may have succeeded.

Step 21.5 - Add Recovery Tools

Provide a restricted command for checking and resolving an ambiguous payout with an audit reason.

Exit Criteria:

  • A worker restart, timeout, or duplicate job cannot pay the same event twice.

Phase 22 - Participant Payout History

Step 22.1 - Build Event History

Show participant events, accepted quantity, reward, event status, and decision reason where safe.

Step 22.2 - Build Payout Status

Show payout pending, paid, failed, or reconciliation-required status with plain-language explanations.

Step 22.3 - Show Payment Proof

Display payment hash, asset, amount, and testnet explorer link only after the data is confirmed.

Step 22.4 - Handle Failed Payouts

Explain that a failed payout is not silently discarded and show the next operational action.

Exit Criteria:

  • A participant can understand whether an event was accepted and whether its reward was paid.

Phase 23 - Sponsor Recovery and Payout Dashboard

Step 23.1 - Build Campaign Summary

Show total accepted quantity, event count, participant count, rejected count, review count, paid amount, pending amount, and remaining budget.

Step 23.2 - Add Material Metrics

Display totals in the selected material unit and preserve the original count or weight semantics.

Step 23.3 - Add Payout Metrics

Separate reserved, paid, failed, ambiguous, and cancelled amounts.

Step 23.4 - Add Operator Metrics

Show event volume and rejection rates by site and operator without exposing unnecessary participant data.

Step 23.5 - Reconcile Dashboard Totals

Calculate dashboard totals from accepted event and payout records, not from mutable client filters.

Exit Criteria:

  • Dashboard totals can be independently reproduced from the audit export.

Phase 24 - Evidence Photo Storage and Privacy

Step 24.1 - Configure Private Object Storage

Use private objects, short-lived access URLs, size limits, content-type checks, and server-side ownership checks.

Step 24.2 - Process Uploads

Reject executable content, unsupported types, oversized files, and uploads without a matching event request.

Step 24.3 - Redact Metadata

Strip unnecessary EXIF and location metadata before review storage where practical.

Step 24.4 - Control Access

Allow access only to authorized operators, reviewers, and sponsor roles with campaign scope.

Step 24.5 - Enforce Retention

Delete or anonymize evidence after the documented retention period and record the deletion audit event.

Exit Criteria:

  • No evidence photo is public by default or included in CKB commitment content.

Phase 25 - Privacy-Filtered Exports

Step 25.1 - Canonical Recovery Export

Create a stable export containing event ID, campaign reference, material, quantity, unit, decision, date bucket, and redacted participant code.

Step 25.2 - Payment Export

Include payout ID, event ID, amount, asset, status, invoice reference, payment hash, and confirmation time.

Step 25.3 - Reconciliation Export

Combine physical partner totals, accepted event totals, rejected totals, and Fiber payout totals with explicit variance fields.

Step 25.4 - Export Manifest

Record file hashes, row counts, campaign rules hash, generation time, and privacy policy version.

Step 25.5 - Verify Export Reproducibility

Generate the same export twice from unchanged data and confirm identical canonical content and hash.

Exit Criteria:

  • Exports contain enough information for audit without publishing participant contact data or photos.

Phase 26 - CKB Campaign Rules Commitment

Step 26.1 - Define Commitment Payload

Commit only campaign ID hash, rules hash, material code, site reference hash, campaign period, and public version metadata.

Step 26.2 - Canonicalize Commitment

Use a deterministic byte representation and document field order and encoding.

Step 26.3 - Build CCC Transaction

Create the testnet commitment transaction with the selected cell format and signer boundary.

Step 26.4 - Wait for Confirmation

Record transaction hash, block reference, payload hash, and explorer link after confirmation.

Step 26.5 - Verify Independently

Read the commitment from CKB and compare it to the campaign rules hash stored by the application.

Exit Criteria:

  • An active campaign has a confirmed CKB commitment before participant events are accepted.

Phase 27 - Daily Collection Commitment

Step 27.1 - Select Daily Records

Select accepted events and their terminal payout states for a closed UTC or campaign-local day.

Step 27.2 - Build Canonical Leaves

Hash only privacy-filtered fields with stable ordering and explicit version information.

Step 27.3 - Build Merkle Root

Create a deterministic root and store leaf count, root hash, and export manifest hash.

Step 27.4 - Commit Root to CKB

Submit the root through CCC and wait for testnet confirmation.

Step 27.5 - Verify Inclusion Proofs

Provide a command and UI view that verifies an event leaf against the committed root.

Exit Criteria:

  • A reviewer can verify that a selected accepted event belongs to the committed daily record set.

Phase 28 - Payout Summary Commitment

Step 28.1 - Build Daily Payment Summary

Canonicalize accepted count, total quantity, paid amount, pending amount, failed amount, asset ID, and payment hashes.

Step 28.2 - Hash the Summary

Create a separate summary hash so recovery and payment totals can be verified without exposing raw participant data.

Step 28.3 - Commit and Confirm

Submit the payout summary commitment to CKB and store the confirmed transaction.

Step 28.4 - Add Commitment Comparison

Compare application totals, export totals, partner reconciliation totals, and the committed summary.

Exit Criteria:

  • The final report links campaign, daily records, payout summary, exports, and CKB transactions.

Phase 29 - Admin Safety Controls

Step 29.1 - Add Campaign Pause

Allow an authorized admin to pause new event acceptance without deleting existing records.

Step 29.2 - Add Payout Emergency Stop

Block new payout submission while allowing reconciliation and read-only operations.

Step 29.3 - Add Exposure Limits

Enforce maximum campaign, daily, participant, and worker payout exposure.

Step 29.4 - Add Operator Revocation

Revoke a compromised or unavailable operator assignment immediately.

Step 29.5 - Audit Administrative Actions

Record actor, scope, reason, previous state, new state, and timestamp for each control change.

Exit Criteria:

  • A safety control blocks the relevant operation in both API and worker paths.

Phase 30 - Notifications and Operational Feedback

Step 30.1 - Define User Notifications

Notify participants about event acceptance, rejection, payout pending, payout success, and payout delay.

Step 30.2 - Define Operator Alerts

Alert operators to invalid QR codes, campaign closure, duplicate attempts, and offline queue failures.

Step 30.3 - Define Sponsor Alerts

Alert sponsors to budget thresholds, payout failures, commitment failures, and reconciliation variance.

Step 30.4 - Redact Notifications

Do not include payment credentials, private URLs, QR secrets, or raw evidence details in notifications.

Exit Criteria:

  • Every terminal user-visible state has a clear explanation and an operational next step.

Phase 31 - Unit and Integration Testing

Step 31.1 - Test Shared Contracts

Test valid and invalid schemas, status transitions, money arithmetic, canonicalization, and hash stability.

Step 31.2 - Test Domain Services

Test campaign activation, participant eligibility, event validation, reward calculation, review, budget reservation, and state transitions.

Step 31.3 - Test Database Services

Test migrations, constraints, organization scope, event uniqueness, payout uniqueness, and transaction rollback.

Step 31.4 - Test API Routes

Test authentication, authorization, validation errors, idempotency, pagination, and redacted responses.

Step 31.5 - Test Worker Jobs

Test duplicate jobs, worker restart, payout retry, commitment retry, export retry, and dead-letter handling.

Exit Criteria:

  • All core domain behavior has deterministic tests independent of external nodes.

Phase 32 - Concurrency, Abuse, and Security Testing

Step 32.1 - Test Duplicate Events

Send concurrent requests with the same event key and confirm one event and one payout reservation.

Step 32.2 - Test Budget Races

Submit events that together exceed the final budget and confirm only the allowed amount is accepted.

Step 32.3 - Test Participant Abuse

Test invite reuse, QR replay, rapid submissions, participant cap bypass, and suspended accounts.

Step 32.4 - Test Operator Abuse

Test wrong-site submissions, revoked assignments, altered quantities, and access to other campaigns.

Step 32.5 - Test Payout Abuse

Test receiver substitution, asset substitution, amount mutation, duplicate payment jobs, and ambiguous status.

Step 32.6 - Write Threat Model

Document threats, controls, residual risks, trusted operators, storage risks, payer risks, and CKB limitations.

Exit Criteria:

  • All high-risk findings have a mitigation, documented acceptance, or a release blocker.

Phase 33 - Browser, Accessibility, and Responsive Tests

Step 33.1 - Test Participant Flow

Test invite claim, consent, QR display, event history, and payout status.

Step 33.2 - Test Operator Flow

Test campaign selection, QR scan, event entry, photo consent, review, and retry behavior.

Step 33.3 - Test Sponsor Flow

Test campaign creation, review, dashboard, exports, commitments, and reconciliation.

Step 33.4 - Test Failure States

Test offline submission, expired campaign, duplicate QR, payment pending, Fiber failure, CKB failure, and unauthorized access.

Step 33.5 - Test Accessibility

Check keyboard navigation, labels, focus states, contrast, error announcements, touch target size, and mobile layout.

Exit Criteria:

  • Critical flows pass in supported desktop and mobile browsers without exposing raw internal JSON as the primary user experience.

Phase 34 - Local Deployment

Step 34.1 - Add Docker Compose

Run web, API, worker, PostgreSQL, Redis, and local object storage with documented health checks.

Step 34.2 - Add Database Bootstrap

Run migrations and seed a complete pilot fixture from one command.

Step 34.3 - Add Mock Fiber Mode

Provide a deterministic fake adapter for local development. Label all mock payments clearly in the UI and reports.

Step 34.4 - Add Mock CKB Mode

Provide a deterministic commitment adapter for tests without confusing it with testnet confirmation.

Step 34.5 - Write Local Runbook

Document startup, reset, seed, test, worker execution, export generation, and troubleshooting commands.

Exit Criteria:

  • A new developer can run the entire happy path and negative cases from a clean checkout.

Phase 35 - Testnet Deployment

Step 35.1 - Provision Services

Provision the database, Redis, private object storage, web app, API, worker, and monitoring.

Step 35.2 - Configure Fiber Testnet

Pin node endpoint, payer credentials, receiver configuration, RUSD asset ID, timeout, and confirmation policy.

Step 35.3 - Configure CKB Testnet

Configure RPC, network, CCC settings, signer boundary, and explorer links.

Step 35.4 - Run Smoke Checks

Run health checks, test invoice creation, test a small payment, test a commitment, and verify logs are redacted.

Step 35.5 - Publish Deployment Documentation

Document environment variables, migrations, worker startup, backups, rollback, and emergency stop procedures.

Exit Criteria:

  • Testnet deployment is reproducible and has no test credentials in the repository.

Phase 36 - Pilot Preparation

Step 36.1 - Prepare Partner Runbook

Document collection procedure, accepted material, quantity measurement, event correction, storage, and daily closeout.

Step 36.2 - Prepare Operator Training

Train operators on QR verification, event preview, rejection reasons, photo consent, offline recovery, and escalation.

Step 36.3 - Enroll Participants

Invite up to 50 participants, collect consent, verify contact path, and provide reward instructions.

Step 36.4 - Prepare QR Materials

Print or distribute site and participant QR materials with revocation and replacement procedures.

Step 36.5 - Prepare Funding and Limits

Fund the testnet payer, set the campaign budget, verify receiver setup, and enable exposure limits.

Step 36.6 - Run Dry Run

Complete a full mock event from QR scan through export and commitment without using real pilot records.

Exit Criteria:

  • Partner, operators, participants, funding, materials, and escalation contacts are ready.

Phase 37 - Pilot Execution

Step 37.1 - Open Campaign

Activate the campaign only after campaign rules commitment and operator readiness checks pass.

Step 37.2 - Monitor Daily Collection

Track events, rejections, reviews, accepted quantities, budget, and operator activity.

Step 37.3 - Settle Rewards

Run payout workers with confirmation and reconciliation controls. Record every payment hash.

Step 37.4 - Close Daily Records

Generate the daily export, reconcile physical totals, build the Merkle root, and commit the daily record hash.

Step 37.5 - Handle Incidents

Use pause, operator revocation, payout emergency stop, and reconciliation procedures when required.

Step 37.6 - Reach Pilot Target

Complete at least 200 accepted collection events while tracking rejected, reviewed, failed, and ambiguous cases separately.

Exit Criteria:

  • Pilot records, payouts, commitments, operator logs, and incident records are complete.

Phase 38 - Reconciliation and Reporting

Step 38.1 - Reconcile Physical Totals

Compare partner weigh-in or count records with accepted digital event totals by day and material.

Step 38.2 - Reconcile Digital Totals

Compare database events, exports, payout reservations, Fiber confirmations, and CKB commitment metadata.

Step 38.3 - Explain Variances

Document rejected events, review decisions, measurement differences, failed payments, and timing differences.

Step 38.4 - Produce Sponsor Report

Include recovered material, accepted events, rejected events, participant count, payout totals, budget remaining, payment hashes, commitment links, and limitations.

Step 38.5 - Produce Public Summary

Publish only privacy-filtered totals and evidence. Do not publish participant identities, raw photos, payer details, or private infrastructure data.

Exit Criteria:

  • A reviewer can trace the sponsor summary to exports, payment records, and CKB commitments without accessing private participant data.

Phase 39 - Release and Handover

Step 39.1 - Freeze Beta Release

Tag the tested application, worker, contract package, database schema, Fiber adapter version, and commitment format.

Step 39.2 - Publish Documentation

Publish setup, architecture, privacy, validation, deployment, partner, pilot, and troubleshooting documentation.

Step 39.3 - Publish Evidence Bundle

Include test results, testnet payment hashes, CKB transaction hashes, export manifests, reconciliation report, and known limitations.

Step 39.4 - Handover Operations

Document payer funding, worker monitoring, backups, retention jobs, emergency stop, operator support, and incident response.

Step 39.5 - Define Maintenance Window

Plan three months of maintenance for dependency updates, Fiber compatibility, bug fixes, partner support, and pilot report corrections.

Exit Criteria:

  • The public repository, deployment, evidence, operational runbook, and maintenance ownership are complete.

API Surface

Authentication and Users

  • POST /api/auth/invite/claim
  • POST /api/auth/logout
  • GET /api/me
  • PATCH /api/me/consent

Sponsor and Sites

  • POST /api/organizations
  • GET /api/organizations/:id
  • POST /api/sites
  • PATCH /api/sites/:id
  • POST /api/sites/:id/operators
  • DELETE /api/sites/:id/operators/:userId

Campaigns

  • POST /api/campaigns
  • GET /api/campaigns
  • GET /api/campaigns/:id
  • PATCH /api/campaigns/:id
  • POST /api/campaigns/:id/submit-review
  • POST /api/campaigns/:id/approve
  • POST /api/campaigns/:id/activate
  • POST /api/campaigns/:id/pause
  • POST /api/campaigns/:id/close

Participants and QR

  • POST /api/campaigns/:id/invites
  • POST /api/participants/qr/rotate
  • GET /api/participants/events
  • GET /api/participants/payouts

Collection Events

  • POST /api/events
  • GET /api/events/:id
  • POST /api/events/:id/validate
  • POST /api/events/:id/review/accept
  • POST /api/events/:id/review/reject
  • POST /api/events/:id/evidence

Payouts

  • GET /api/payouts
  • GET /api/payouts/:id
  • POST /api/payouts/:id/reconcile
  • POST /api/admin/payouts/emergency-stop

Exports and Commitments

  • POST /api/campaigns/:id/exports
  • GET /api/exports/:id
  • POST /api/campaigns/:id/commitments/campaign
  • POST /api/campaigns/:id/commitments/daily
  • POST /api/campaigns/:id/commitments/payouts
  • GET /api/commitments/:id
  • GET /api/commitments/:id/proof/:recordId

Application Surfaces

Participant Pages

  • invite claim and sign in;
  • campaign briefing;
  • consent;
  • QR identity;
  • event history;
  • payout history;
  • payment detail;
  • privacy and retention settings;

Operator Pages

  • assigned campaign list;
  • QR scanner;
  • event entry;
  • evidence capture;
  • event confirmation;
  • recent event queue;
  • rejected and review-needed events;
  • site closeout summary;

Sponsor Pages

  • organization overview;
  • site and operator setup;
  • campaign builder;
  • campaign review;
  • active campaign dashboard;
  • recovery metrics;
  • payout metrics;
  • export center;
  • CKB commitment evidence;
  • reconciliation report;

Admin Pages

  • users and roles;
  • campaign safety controls;
  • payout emergency stop;
  • reconciliation queue;
  • audit events;
  • system health;
  • retention and storage status;

Build Order

  1. Lock pilot partner, site, material, rules, and limitations.
  2. Create workspace, applications, packages, CI, and configuration.
  3. Implement contracts, money utilities, and validation schemas.
  4. Implement database migrations and authorization boundaries.
  5. Build organization, site, operator, campaign, and activation workflows.
  6. Implement participant invites, consent, and QR identity.
  7. Build operator collection and event intake.
  8. Implement deterministic validation and manual review.
  9. Add exactly-once acceptance and budget reservation.
  10. Implement payout records and the Fiber adapter.
  11. Run mock settlement tests and then confirm a funded testnet payment.
  12. Build participant payout history and sponsor dashboards.
  13. Add evidence storage, retention, exports, and reconciliation.
  14. Implement campaign, daily event, and payout summary commitments.
  15. Add admin safety controls, notifications, and operations tooling.
  16. Complete security, concurrency, browser, accessibility, and deployment tests.
  17. Run the pilot, reconcile physical and digital totals, and publish the evidence bundle.

Funding Milestone Mapping

Milestone 1 - Foundation and Pilot Rules

Includes Phases 0-9:

  • partner and site selection;
  • campaign rules;
  • repository and infrastructure foundation;
  • shared contracts;
  • database;
  • organization, operator, and campaign setup;
  • campaign canonicalization and activation.

Milestone 2 - Participant and Collection Workflow

Includes Phases 10-17:

  • invitations;
  • QR identity;
  • consent;
  • operator collection;
  • event intake;
  • validation;
  • manual review;
  • exactly-once acceptance.

Milestone 3 - Fiber Settlement and CKB Audit

Includes Phases 18-28:

  • payout reservations;
  • Fiber adapter;
  • confirmed RUSD payments;
  • reconciliation;
  • participant and sponsor reporting;
  • private evidence storage;
  • exports;
  • campaign, daily, and payout commitments.

Milestone 4 - Pilot, Security, and Handover

Includes Phases 29-39:

  • safety controls;
  • notifications;
  • automated and security testing;
  • browser and accessibility testing;
  • local and testnet deployment;
  • partner preparation;
  • 200-event pilot;
  • reconciliation;
  • public release and maintenance handover.

Key Implementation Rules

  • Do not describe an operator-approved collection record as trustless physical proof.
  • Do not accept an event without a server-side operator assignment check.
  • Do not calculate rewards from client-submitted amounts.
  • Do not use floating-point arithmetic for RUSD or campaign budgets.
  • Do not let a retry create a second event or payout.
  • Do not call Fiber spending RPCs from browser code.
  • Do not retry ambiguous payments until they are reconciled.
  • Do not expose payer credentials, QR secrets, private object URLs, or raw private evidence.
  • Do not mutate an activated campaign rule set.
  • Do not put personal information, photos, or payment secrets in CKB commitment payloads.
  • Do not present mock Fiber or mock CKB results as live evidence.
  • Do not call a payout paid until the required confirmation check succeeds.
  • Do not publish a reconciliation total that cannot be reproduced from the export manifest.

Open Technical Decisions

These decisions must be closed during the first validation work and recorded before implementation depends on them:

  • exact Fiber node and RPC version;
  • exact RUSD testnet asset ID and base-unit precision;
  • participant authentication method;
  • CKB commitment cell format;
  • CCC signer and funding boundary;
  • object storage provider and retention configuration;
  • QR payload signing or integrity method;
  • count versus weight measurement for the selected material;
  • accepted clock-skew window;
  • event correction policy after operator approval;
  • daily commitment timezone;
  • sponsor report publication policy;
  • minimum browser and mobile support;
  • support process for lost participant QR identity;
  • pilot photo retention duration.

Definition of Done

Product

  • A sponsor can create and activate one bounded campaign.
  • An operator can verify a participant QR identity at the correct site.
  • An operator can record count or weight and optional evidence.
  • A participant can see event and payout status.
  • A sponsor can inspect recovery and payment totals.

Validation

  • Duplicate events are rejected.
  • Wrong campaign, material, site, operator, participant, time, and quantity are rejected.
  • Participant, event, and budget limits are enforced under concurrency.
  • Review decisions are permissioned and audited.

Fiber

  • At least one confirmed RUSD testnet payment exists.
  • Payout reservation is exactly once.
  • Payment amounts and assets are verified against invoices.
  • Ambiguous payments are reconciled without duplicate settlement.

CKB

  • Campaign rules commitment is confirmed.
  • Daily collection-record commitment is confirmed.
  • Payout summary commitment is confirmed.
  • Inclusion and export verification tools work.

Security and Privacy

  • Payer credentials never reach clients.
  • QR secrets and private evidence are protected.
  • Public exports do not expose participant contact data or photos.
  • Retention and deletion behavior is documented and tested.
  • High-risk threat-model findings are resolved or explicitly accepted.

Grant Evidence

  • Repository is public and reproducible.
  • Test results and build instructions are published.
  • Fiber transaction hashes and CKB transaction hashes are recorded.
  • At least 200 accepted events are included in the pilot evidence.
  • Physical-versus-digital reconciliation is documented.
  • Demonstration video shows the participant, operator, sponsor, payout, and audit workflows.
  • Three-month maintenance responsibilities are assigned.