Snapcharge
The definitive guide to Snapcharge what it is, what it stores, how verification works, lifecycle/state machine, and developer patterns.
A Snapcharge is an append‑only transactional event inside a Snapgate. It captures:
- the commercial outcome (paid/free/unpaid/canceled/refund),
- the exact project state at that moment (repository structure, commit/tag, terms, policies, price), and
- a pair of cryptographic proofs (integrity + signer) that make the record tamper‑evident.
Think of a Snapcharge as a time capsule for a project version as delivered to a specific user through a specific Snapgate.
Snapcharges are the only way a Snapshot's history grows; every access claim (initial purchase, upgrades, free updates, enforcement changes, refunds) is recorded as a new Snapcharge.
Core Responsibilities
- Record Access Event Log whether access was download/invite, one‑time/subscription, and whether delivery finalized.
- Preserve State Freeze the project's structure, license, policies, and price as they existed at the time of the event.
- Verify Integrity Attach verifications so anyone can independently check that the record has not been altered.
- Link the Chain Tie the event to its Snapgate, Booth, Project, and Snapshot identifiers for audit and traversal.
Lifecycle & State Machine
A Snapcharge is created at initiation (when the user claims/starts an access event) and finalized when the outcome is known. Some events are free and finalize instantly; others involve a payment provider.
Timestamps (typical):
initializeAt
when initiation started.completedAt
when the commercial outcome finalized.SnapshotstartAt
/snapshotCompletedAt
window for writing to the Snapshot container.snapshotCreatedAt
when the first Snapshot entry for this charge was created.snapshotExpireAt
optional TTL for time‑boxed claims (e.g., invitation windows).
Data Model (Developer Reference)
Field names mirror the current schema; groupings are for explanation.
Identity & Linking
code: string
unique idempotency key for the Snapcharge.isPrimary: boolean
primary charge for a flow (e.g., first delivery in a bundle).userId: Id<'users'>
,boothId: Id<'booths'>
,SnapgateId: Id<'Snapgates'>
foreign keys.type: 'projects' | 'applications' | 'solutions'
entity class.access: 'download' | 'invite'
access modality delivered.
Commercials & Payment
type: 'perpetual' | 'subscription'
amount: number
amount paid (post‑discount, pre‑fees as defined by platform).originalAmount: number
list price at the time.applicationPercentage: number
booth/owner share percentage.netAmount: number
,stripeFee: number
,applicationFee: number
exchangeRate?: number
when currency conversion is involved.couponCode?: string
paymentIntentId?: string
gateway identifier (e.g., Stripe PI).hasAnyRefunds?: boolean
,refunds?: Refund[]
Status & Control
status: 'paid' | 'free' | 'unpaid' | 'processing' | 'canceled'
isSuccess: boolean
true when the commercial outcome grants entitlement (paid/free).isCompleted: boolean
terminal state reached.isLocked: boolean
access locked due to enforcement.schedule?: { isActive: boolean; isDone: boolean }
background jobs.
Version & Project State (Frozen)
commit?: Commit
commit or tag resolved at fulfillment.structure: string
serialized repository structure for deterministic replay.termsAndConditions: string
,refundPolicy: string
,refundConditions: string[]
,disputePeriod: number
,acceptsRefunds: 'yes' | 'no'
gitUsername?: string
for invite access.metadata?: Record<string, any>
caller-supplied annotations.
Snapshot Linkage
snapshot: string
serialized snapshot view at write time (audit cache).snapshotCreatedAt: number
,SnapshotstartAt: number
,snapshotExpireAt: number
,snapshotCompletedAt?: number
Verification (Tamper‑evident)
verifications?: Verification[]
where each entry:reason: 'initial' | 'final' | 'update' | 'refund'
createdAt: number
integrity: { hash: string; token: string; kid: string }
signer: { hash: string; token: string; kid: string }
Note: The Snapcharge stores the project's state snapshot, not pointers to mutable rows. This ensures point‑in‑time reconstruction even if the live project changes later.
What Exactly Is Signed?
To avoid circularity, verification runs over the canonical Snapcharge payload with the following rules:
- Included: all business‑meaningful fields that describe the event: identity/linking, commercials, status, version & project state, snapshot linkage, timestamps, schedule flags, and metadata.
- Excluded: the
verifications[]
array itself and any volatile transport headers.
Deterministic serialization:
- Objects are serialized with stable key ordering (UTF‑8,
\n
newlines), - Numbers encoded as canonical JSON numbers (no trailing zeros),
null
omitted unless semantically required,- Arrays preserved in order.
The resulting bytes are hashed to produce integrity.hash
, and a JWT containing that hash is signed with the private key designated by integrity.kid
→ integrity.token
.
Then the signer layer hashes { integrity.hash, integrity.kid, integrity.token }
→ signer.hash
, and signs that with its private key (signer.kid
) → signer.token
.
This two‑layer (circular) scheme ensures that if either token or hash were altered, validation fails.
Verification Procedure (High‑level)
- Parse the Snapcharge JSON from the Snapshot's
Snapcharges[]
cache. - Canonicalize it (apply deterministic serialization rules) excluding
verifications
. - Hash → compare with
integrity.hash
. - Verify JWT
integrity.token
using the published public key forintegrity.kid
. - Hash signer input
{ integrity.hash, integrity.kid, integrity.token }
→ compare withsigner.hash
. - Verify JWT
signer.token
with the public key forsigner.kid
. - Repeat for each
verifications[]
record; check that a terminal record exists for terminal statuses (paid/free/canceled/refund).
See Public Verification for full details on key distribution, JWT formats, and validation logic.
Example (Annotated)
{
...
"commit": { "type": "tag", "value": "v1.2.0" },
"structure": "{\n \"/\": { \"type\": \"dir\", \"children\": [ ... ] }\n}",
"termsAndConditions": "No redistribution. Single-seat license.",
"refundPolicy": "7-day refund for technical issues.",
"refundConditions": ["Not compatible with Node <18"],
...
"disputePeriod": 14,
"acceptsRefunds": "yes",
"SnapshotstartAt": 1755139207,
"snapshotCreatedAt": 1755139208,
"snapshotCompletedAt": 1755139208,
"snapshotExpireAt": 0,
"paymentIntentId": "pi_3P...",
...
"verifications": [
{
"reason": "final",
"createdAt": 1755139208,
"integrity": {
"hash": "d1c6...",
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6\n...",
"kid": "uhp-integrity-20250809.public.json"
},
"signer": {
"hash": "a04e...",
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6\n...",
"kid": "uhp-signer-20250809.public.json"
}
}
]
}
Interactions with Snapgate & Snapshot
- Snapgate creates the context (user↔project access) and enforces policy (revoke/suspend). Snapcharge records the effect of those actions.
- Snapshot is the container that aggregates serialized Snapcharges and the serialized Snapgate for durable audit and reconstruction.
Rule of thumb: Snapgate decides, Snapcharge records, Snapshot preserves.
Refunds & Disputes
Refunds are represented as:
- A Snapcharge in terminal
paid/free
state withhasAnyRefunds = true
plus - A follow‑up Snapcharge (or verification entry with
reason = 'refund'
) that captures the refund details and updated net amounts.
Disputes (chargebacks) must not mutate past entries; they are captured as new events and reflected in the Snapshot.
Enforcement & Locking
When policy is violated (e.g., redistribution, account sharing):
- The Snapgate is updated (revoke/suspend/lock).
- A new Snapcharge captures the enforcement outcome (
isLocked = true
, policy references). Past Snapcharges remain intact.
Mini Flow Diagram
Snapcharge is the foundational audit and transactional unit within Uhpenry's ecosystem. By recording every access event in an append-only, tamper-evident format, Snapcharges ensure that project state, commercial outcomes, and enforcement actions are fully auditable, verifiable, and reconstructible.
Together with Snapgate (which enforces access policy) and Snapshot (which preserves serialized history), Snapcharge provides a secure, transparent, and immutable ledger of all interactions with a project. This design guarantees that every payment, download, invite, refund, and enforcement action can be independently verified, supporting accountability, dispute resolution, and long-term archival without relying on mutable databases.
In essence, Snapcharge ensures that every project interaction is trustworthy, traceable, and tamper-proof, forming the backbone of Uhpenry's secure distribution and collaboration model.
Note: This guide is living documentation. We welcome contributions and corrections via GitHub or support@uhpenry.com.
Snapgate
The secure, account‑bound access checkpoint that governs terms acceptance, moderation, and the creation of verifiable Snapcharges and Snapshots.
Gated Source
Explains the Gated Source concept and how it affects access to projects, licensing, monetization, enforcement, and developer integration.