Skip to main content

What We Learned

A singleton service that issues scarce, cryptographically signed tokens needs three independent enforcement layers — not one. The golden-press service protects a hard cap of 5 Golden Tickets using: (1) pg_advisory_xact_lock(42) as a blocking transaction-scoped lock that serialises all issuance attempts, (2) an application-level count >= 5 guard that rejects before INSERT, and (3) a database CHECK (ticket_number <= 5) constraint as the final safety net. Any single layer can be circumvented by bugs, race conditions, or operator error. All three together make double-issuance require simultaneous failures across the application, the lock, and the schema — which is the security posture a value-bearing token demands.

The JSON Envelope Pattern

The original scaffold used a canonical string format (ticket:{id}:user:{uid}:number:{num}:timestamp:{ts}) for Ed25519 signing. This was replaced with a JSON envelope {ticket_number, recipient, timestamp} that the signature field is appended to after signing. Verification strips the signature, rebuilds canonical JSON, and checks Ed25519. The JSON envelope is better for downstream consumers because: any language with JSON + Ed25519 support can verify a ticket without parsing a custom format. The Verifier type is the SDK extraction point — only the 64-char hex public key is needed.

The Anti-Gaming Rewrite

The scaffold’s thresholds (7 days, 50 lines, /24 subnet, 24h window) were placeholders from the SRS draft. Production thresholds (30 days repo, 100KB size, 90 days account, 1 check/IP/hour) reflect the actual gaming vectors observed during design review. The key design decision: all 4 rules run non-short-circuit so the caller sees every violation at once, not one at a time.

Applicability

This three-layer enforcement pattern (lock → app guard → DB constraint) applies to any system issuing scarce resources: limited invitations, numbered editions, coupon allocations. The singleton deployment + advisory lock combination eliminates the distributed consensus problem entirely — at the cost of horizontal scalability, which a 5-item system doesn’t need.