Skip to content

Phase 2: fula-ingest node - verified byte ingress (client-side CID, quota-gated) #74

Description

@ehsan6sha

Phase 2 of the decentralization roadmap (uploads axis; cross-repo with functionland/fula-api).

Ships: docker/fula-ingest/ — a small Go service any provider/operator can run that accepts encrypted chunk BYTES so uploads no longer depend on a single gateway for the byte path:

  • PUT /v0/block?cid=<declared>: verifies blake3 raw-leaf CID over the body BEFORE storing (tampered byte => 422, hard rejection - the server-side half of tamper-evidence), then kubo block/put?cid-codec=raw&mhtype=blake3 and double-checks kubo's returned key.
  • S1 quota gate (never unmetered ingestion): mirrors the gateway exactly - GET {STORAGE_API_URL}/api/v1/storage with the client's Bearer JWT, short per-token cache; INGEST_QUOTA_MODE=strict|open (default mirrors gateway fail-open).
  • GET /health; size cap (INGEST_MAX_BLOCK_BYTES, default 4 MiB - chunks are 256 KiB + AEAD); bounded concurrency; retention = no GC (kubo default) until proof-of-possession exists (per plan).
  • Dockerfile + compose snippet; discovery/announce wiring (relay list) comes later - v0 clients receive the endpoint via config.

Verify (e2e on test infra): valid chunk accepted + retrievable from kubo by CID; tampered byte rejected 422 and NOT stored; over-quota/missing-JWT behavior per mode; works on ARM (fxblox additive container) and x86.

Scale invariant: per-chunk O(1), streaming, no per-item on-chain anything.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions