Crumpet Media β€” Technical Architecture (v0 + v0.1)

0) Glossary (ELI5)

  • Article package (AOM): a shoebox with an index card, the story, and pictures. Its fingerprint (CID) proves nothing inside has changed.

  • CID: IPFS fingerprint; if the content changes, the fingerprint changes.

  • Score: Upvotes (counted CRUMBS) minus Downvotes (25/50 CRUMBS).

  • Vault: protocol treasury (downvotes, some upvote share, slashed bonds, unrefunded flags).

  • Flag: a β€œplease review” deposit. Refunded if DAO takes action; else kept by Vault.

  • CIN (Layer‑3 node): a server that fetches articles, builds language search indexes, and serves fast queries. Nodes cross‑check each other so you don’t trust just one.


1) Article Object Model (AOM v1)

Package layout (UnixFS folder or CAR):

bashCopyEdit/crumpet.json             # DAG-CBOR manifest (also emitted as JSON for devs)
/body.md                  # Markdown (safe subset)
/preview.html             # OPTIONAL deterministic HTML, trust-but-verify
/media/<hash>.<ext>       # images; referenced by relative paths in body.md

Constraints (v0):

  • Max package size: 4β€―MB

  • ≀ 10 images, max 2560px long edge

  • No embeds (no iframes/scripts). Images only, bundled locally.

Manifest (JSON view):

Determinism: A reference Rust renderer (WASM in browser). If /preview.html mismatches a local render of /body.md, the client discards it and uses the local render.


2) Token‑Economics & User Actions (Single‑Action Rule)

One action per wallet per article. A wallet may perform exactly one among:

  • Upvote (with optional extra tip),

  • Dislike (βˆ’25),

  • DownVote (βˆ’50),

  • Flag (deposit for review).

Once recorded, the wallet cannot perform any other action on that article (no second vote, no flag after voting, etc.). This prevents gaming and ensures fairness.

ELI5: You get one button press per article. Choose wisely.


3) Voting & Scoring (Linear, capped; unlimited tips)

DAO‑tunable parameters (timelocked):

  • MIN_UP = 10 CRUMBS (minimum to cast an upvote)

  • MAX_UP_WEIGHT = 100 CRUMBS (per‑vote counted cap; overflow becomes tip)

  • DISLIKE = 25 CRUMBS (counts βˆ’25; 100% to Vault)

  • DOWNVOTE = 50 CRUMBS (counts βˆ’50; 100% to Vault)

Upvote handling (example):

  • Send amount. If amount < MIN_UP, revert.

  • counted = min(amount, MAX_UP_WEIGHT) β†’ contributes +counted to score.

  • tip = amount - counted β†’ extra support, no extra weight.

  • Split: of the counted part, 20% to Vault, 80% to Author; 100% of tips to Author.

Down actions:

  • Dislike deducts 25 from score; 25 CRUMBS β†’ Vault.

  • DownVote deducts 50; 50 CRUMBS β†’ Vault.

Score: score = βˆ‘countedUp βˆ’ βˆ‘downAmounts.

Why wallet‑split is neutral: cost per counted unit is 1 CRUMBS; the cap is per vote, and you only get one vote per article. Splitting across wallets is Sybil behavior the single‑action rule removes at the origin.


4) Flags, Disputes, and Bonds (by time, not blocks)

DAO‑tunable:

  • FLAG_FEE = 25 CRUMBS (refunded if action taken)

  • FLAGS_TO_OPEN = 3

  • GRACE_SECONDS = 10 days (time‑based, not block‑based)

  • PUBLISH_BOND = 100 CRUMBS (posted by author on publish)

Lifecycle:

  • Publish: author posts B to the contract.

  • Flag: any wallet can flag (once per article) by paying F; optional noteCid for context.

    • A flag consumes the one‑action allowance for that wallet on that article.

  • Dispute: when a CID has K flags, a case opens.

  • Resolve (DAO):

    • Action taken = true: refund F to all flaggers in that case; slash B to Vault (if still before publish.createdAt + GRACE_SECONDS); attach Community Notes (IPFS CIDs).

    • No action: flags kept by Vault; author’s bond auto‑refundable after GRACE_SECONDS.

  • Refunds:

    • autoRefundBond(cid) callable by anyone once now β‰₯ publish.createdAt + GRACE_SECONDS and there’s no upheld action.

    • Flag refunds (on action taken) are pull‑based: each flagger calls claimFlagRefund(caseId).

ELI5: You leave a small deposit when you publish. If a valid complaint is upheld, your deposit is taken. If not, you get it back after ~10 days. Flaggers get their deposit back only if the DAO acts.


5) Contracts (Kasplex EVM) β€” Key Interfaces

Modular, with a separate Config contract (DAO‑timelocked). Events are explicit for indexers and analytics.

5.1 ArticlesRegistry

5.2 Actions (Upvote/Down/Flag) with Single‑Action Enforcement

5.3 Disputes & Bonds (time‑based grace)

5.4 Vault & Node Rewards

  • Vault accrues: 20% counted upvotes, 100% downvotes, unrefunded flags, slashed bonds.

  • DAO allocates up to 40% of Vault net inflows to Node Rewards Pool.

5.5 Config (DAO‑timelocked)

  • Parameters: MIN_UP, MAX_UP_WEIGHT, DISLIKE, DOWNVOTE, FLAG_FEE, FLAGS_TO_OPEN, GRACE_SECONDS, PUBLISH_BOND, NodeRewards splits/percentages.

  • Emits ConfigChanged(...).


6) Layer‑3: CIN Nodes (Storage + Indexing + Serving)

6.1 Protocols & Transport (low‑latency, modern)

  • Node↔Node (control/data):

    • gRPC over HTTP/2 (Rust tonic) for control plane (snapshots, health, attestations).

    • libp2p (Noise) over QUIC for P2P gossip (language snapshot announcements) and fast peer discovery.

    • HTTP/3 (QUIC) and IPFS for snapshot/package transfers (concurrent range fetches).

  • Node↔UI (client apps):

    • HTTP/2 JSON API (search/article/trending).

    • WebSocket streams for live updates (/ws/events), low latency.

    • Optional gRPC‑Web (via Envoy) if you prefer a single RPC stack in the browser.

ELI5: We use the fast lanes on the internet (HTTP/2, QUIC, WebSockets, gRPC) so searches feel instant and nodes share data quickly.

6.2 Federation & Integrity (language‑sharded)

  • Each node builds per‑language index segments for its primary languages (en, de, …).

  • Nodes fetch signed snapshots for other languages from peers, requiring 2‑of‑3 matching Merkle roots.

  • Regular CID spot checks verify fetched segments aren’t lying.

  • Snapshots record renderer/analyzer versions; mismatches are rejected.

6.3 Incentives (from Vault)

  • Node Rewards Pool gets up to 40% of Vault net inflows (DAO‑tunable).

  • Epoch payouts (e.g., weekly):

    • 40% Uptime share β€” pass SLA probes.

    • 40% Build share β€” # of language snapshots built that achieved majority/committee acceptance.

    • 20% Serve share β€” optional, via hashed β€œserved” receipts (rate‑limited to prevent gaming).

6.4 Hardware targets

  • Builder (2 languages): 2 vCPU, 4–8β€―GB RAM, 100β€―GB SSD, local IPFS node.

  • Fetcher/serve‑only: 2 vCPU, 4β€―GB RAM, 50β€―GB SSD.

  • Pruning: retain last N snapshots; older on IPFS.

6.5 Node APIs

HTTP/2 JSON:

gRPC (excerpt, proto sketch):


7) Frontend & UX

  • Next.js + TypeScript, wagmi/RainbowKit on Kasplex EVM.

  • Renderer: Rustβ†’WASM; Sanitizer: strict allow‑list.

  • Service Worker: cache AOM packages; multi‑source fetch race (local IPFS β†’ node cache β†’ gateways).

  • Publish UX: require 3 IPFS pin‑acks before enabling on‑chain publish.

  • Vote UX: show one chooser (Upvote/Dislike/DownVote/Flag). After selection, lock UI.

  • Dispute UX: show label and Community Notes if action taken; do not remove content.


8) Internationalization

  • lang required in manifest.

  • Day‑1 analyzers: EN, DE, ES, FR, PT, IT, NL, PL, TR, RU, ZH‑Hans, ZH‑Hant, JA, KO, AR, HI.

  • Browsers’ built‑in translation works (plain HTML).

  • Adding languages = add analyzer + tests (no AOM change).


9) Security & Best Practices

  • Contracts: Reentrancy guards, Checks‑Effects‑Interactions, SafeERC20, pull refunds (flags).

  • Governance: Timelock on Config; multisig; parameter change rate limits.

  • Time sources: use block.timestamp as wall‑clock for GRACE_SECONDS. Avoid assuming fixed block cadence.

  • Indexers: reject snapshots with renderer/analyzer major version mismatches; keep a denylist of malicious peers.

  • Content: validate image types/sizes; strip scripts/event handlers; forbid external‐scheme links.


10) Examples & Edge Cases

Single‑action constraint:

  • If a wallet Upvoted, it cannot later Dislike, DownVote, or Flag.

  • If a wallet Flagged, it cannot later Upvote or DownVote.

  • Attempts revert with AlreadyActed().

Upvote overflow:

  • Send 120 CRUMBS β†’ counted 100, tip 20; one vote recorded; can’t vote again.

Flags & refunds:

  • Case opened at 3 flags.

  • DAO action taken: flaggers each call claimFlagRefund (25 back).

  • No action within 10 days: author’s autoRefundBond succeeds; flags stay in Vault.

Article updates:

  • New edition = new CID; previousCid links history. Scores are per‑edition; UI may aggregate.


11) Parameter Table (initial defaults)

Parameter
Default
Notes

MIN_UP

10 CRUMBS

per vote minimum

MAX_UP_WEIGHT

100 CRUMBS

per vote cap for counted weight

DISLIKE

25 CRUMBS

βˆ’25; 100% to Vault

DOWNVOTE

50 CRUMBS

βˆ’50; 100% to Vault

Upvote split

20% of counted β†’ Vault

80% counted + 100% tips β†’ Author

FLAG_FEE

25 CRUMBS

refunded iff action taken

FLAGS_TO_OPEN

3

threshold to open case

GRACE_SECONDS

10 days

time‑based

PUBLISH_BOND

100 CRUMBS

slashed on action within grace

Node Rewards Pool

up to 40% Vault net inflow

DAO‑tunable

Node split

40% uptime / 40% build / 20% serve

DAO‑tunable


12) Repo Skeleton

Example proto (snippet)


13) CONTRIBUTING.md (short)

Coding standards

  • Contracts: Solidity ^0.8.24, NatSpec, events for all state changes, Foundry tests (unit/fuzz/invariant), Slither/Static analysis in CI.

  • Rust: stable toolchain, clippy clean, rustfmt, property tests where applicable, no unsafe unless justified.

  • TypeScript: strict TS, ESLint+Prettier, never ignore types for chain amounts; use BigInt/ethers.js BigNumber.

Testing

  • Contracts: 100% branch coverage targets for Actions/Disputes/Vault; reentrancy + refund invariants.

  • Renderer: golden vectors, sanitizer adversarial cases (XSS payload corpus).

  • Indexer: determinism checks (same inputs β†’ identical snapshot roots), multilingual tokenizer tests, p95 latency benchmarks.

Security

  • No external calls before state changes (CEI).

  • Use pull patterns for refunds (flags).

  • Limit parameter change rates in Config.

  • Document threat models (Sybil, brigading, snapshot forgery).

CI

  • Lint, build, test (contracts, Rust, web).

  • Snapshot reproducibility check on deterministic inputs.

  • Container image builds & SBOM.


14) Engineer Hand‑off Checklist


Final notes

  • Single‑action rule is enforced on‑chain and reflected in UI (buttons lock after an action).

  • Grace periods are time‑based (GRACE_SECONDS) so they work with a based rollup.

  • Connectivity uses gRPC/HTTP2/WebSockets/QUIC for speed; libp2p gossip advertises snapshots; IPFS (HTTP/3 where available) moves the bytes.

  • Everything is DAO‑tunable with a timelock; indexers include the active parameter set in snapshot metadata.

Last updated