diff --git a/skills/foc-platform/SKILL.md b/skills/foc-platform/SKILL.md new file mode 100644 index 0000000..3c6b91a --- /dev/null +++ b/skills/foc-platform/SKILL.md @@ -0,0 +1,45 @@ +--- +name: foc-platform +description: Use when reasoning about Filecoin Onchain Cloud architecture, PDP, Warm Storage Service, Filecoin Pay, Filecoin Beam, Filecoin Pin/IPFS indexing, storage economics, or durable-state anchoring patterns. +--- + +# foc-platform + +Use this for product, protocol, and architecture decisions around Filecoin +Onchain Cloud. For SDK-level code and API usage, also use +`../synapse-sdk/SKILL.md`. + +## Hard Rules + +- Separate bytes, proofs, payments, and client orchestration. +- Treat Filecoin as a durable service plane, not a live message bus. +- PDP proves possession, not authorship, freshness, or semantic correctness. +- Keep author, uploader, payer, publisher, and helper roles explicit. +- Publish external pointers only after the upload result is final. +- Dataset reuse is economic state; accidental dataset creation costs money. +- Beam/CDN changes retrieval UX and egress economics, not storage correctness. +- IPFS indexing changes discoverability, not ownership. + +## Fast Path + +1. Product model, costs, and service boundaries: + `references/core/architecture.md` +2. Official sources and freshness rules: + `references/core/source-ledger.md` +3. Durable-state anchoring patterns: + `references/use-cases/durable-state.md` +4. Public content, IPFS indexing, and CDN interplay: + `references/use-cases/public-content.md` +5. Authority, economics, and topology bugs: + `references/debugging/failure-modes.md` +6. Role-splitting edge cases: + `references/edge-cases/authority.md` + +## References + +- `references/core/architecture.md` +- `references/core/source-ledger.md` +- `references/use-cases/durable-state.md` +- `references/use-cases/public-content.md` +- `references/debugging/failure-modes.md` +- `references/edge-cases/authority.md` diff --git a/skills/foc-platform/references/core/architecture.md b/skills/foc-platform/references/core/architecture.md new file mode 100644 index 0000000..eec8099 --- /dev/null +++ b/skills/foc-platform/references/core/architecture.md @@ -0,0 +1,45 @@ +--- +description: Current Filecoin Onchain Cloud architecture and economics. +--- + +# Architecture + +Verified `2026-03-23`. + +## Layers + +- `Synapse SDK`: client orchestration, provider selection, payments prep, + upload/retrieval APIs +- `FWSS`: warm-storage service contract and dataset lifecycle +- `PDPVerifier`: proof system that verifies providers still hold bytes +- `Filecoin Pay`: continuous settlement rails in USDFC +- `FilBeam`: CDN / performance retrieval path +- `Filecoin Pin + IPNI`: public content discovery path for IPFS-style content + +## Data Model + +- bytes -> `pieceCid` +- one provider + one dataset -> one payment relationship +- multi-copy storage -> one committed copy per provider +- dataset metadata drives reuse +- piece metadata labels a single object + +## Economics + +- base storage: `2.50 USDFC / TiB / 30-day month` +- minimum dataset rate: `0.06 USDFC / month` +- new dataset sybil fee: `0.1 USDFC` +- CDN setup on new CDN dataset: `1.0 USDFC` +- CDN egress: `14 USDFC / TiB downloaded` +- storage service expects roughly `30` days of prepayment runway + +## Product Choices + +- PDP only: + durable storage + retrievability +- PDP + Beam: + low-latency retrieval +- PDP + IPFS indexing: + public gateway/IPNI discoverability +- PDP + signed payload: + durable provenance / state anchoring diff --git a/skills/foc-platform/references/core/source-ledger.md b/skills/foc-platform/references/core/source-ledger.md new file mode 100644 index 0000000..0ce9fca --- /dev/null +++ b/skills/foc-platform/references/core/source-ledger.md @@ -0,0 +1,36 @@ +--- +description: Official source order and freshness notes for Filecoin Onchain Cloud. +--- + +# Source Ledger + +Verified `2026-03-23`. + +## Primary Sources + +- docs: + - `https://docs.filecoin.cloud/` + - `https://docs.filecoin.cloud/core-concepts/architecture/` + - `https://docs.filecoin.cloud/core-concepts/pdp-overview/` + - `https://docs.filecoin.cloud/core-concepts/fwss-overview/` + - `https://docs.filecoin.cloud/core-concepts/filecoin-pay-overview/` + - `https://docs.filecoin.cloud/developer-guides/storage/storage-costs/` +- SDK / contracts / examples: + - `https://github.com/FilOzone/synapse-sdk` + - `https://github.com/FIL-Builders/fs-upload-dapp` + +## Conflict Rules + +- Economics and service concepts: docs win. +- Current API and export names: SDK source wins. +- Example-app behavior is evidence, not protocol truth. +- Prefer exact dates when discussing versions or publish times. + +## Fresh Facts + +- docs host is `docs.filecoin.cloud` +- current npm latest: + - `@filoz/synapse-sdk` = `0.40.0` + - `@filoz/synapse-core` = `0.3.1` +- current public architecture still centers on FWSS + PDP + Filecoin Pay + + Synapse SDK, with Beam/CDN and IPFS indexing as optional retrieval paths diff --git a/skills/foc-platform/references/debugging/failure-modes.md b/skills/foc-platform/references/debugging/failure-modes.md new file mode 100644 index 0000000..23bf301 --- /dev/null +++ b/skills/foc-platform/references/debugging/failure-modes.md @@ -0,0 +1,58 @@ +--- +description: High-signal product and architecture failure modes on Filecoin Onchain Cloud. +--- + +# Failure Modes + +## Authority Bugs + +Symptoms: + +- one process builds bytes, another publishes the pointer +- helper service can mutate anchor fields after upload +- client-authored state becomes server-authored storage + +Fix: + +- collapse build/sign/upload/publish onto the actual state authority + +## Economic Bugs + +Symptoms: + +- storage costs spike unexpectedly +- many tiny datasets appear +- CDN costs look wrong + +Check: + +- volatile dataset metadata +- accidental `source` changes +- unnecessary new datasets +- CDN setup fee vs recurring egress +- copy count inflation + +## Partial-Success Bugs + +Symptoms: + +- app treats returned upload result as full success +- one failed provider marks the whole job failed + +Check: + +- `complete` +- committed `copies[]` +- whether retries replaced failed providers + +## Topology Bugs + +Symptoms: + +- system stops working when helper services go down +- durable storage path is also the live coordination path + +Fix: + +- keep helper services optional +- keep durable anchoring separate from live transport diff --git a/skills/foc-platform/references/edge-cases/authority.md b/skills/foc-platform/references/edge-cases/authority.md new file mode 100644 index 0000000..25f99d0 --- /dev/null +++ b/skills/foc-platform/references/edge-cases/authority.md @@ -0,0 +1,43 @@ +--- +description: Role-splitting edge cases for Filecoin Onchain Cloud integrations. +--- + +# Authority + +## Keep These Roles Separate + +- author: + who created the bytes +- uploader: + who executed the storage operation +- payer: + who funds the rails +- publisher: + who exposes the external pointer +- helper: + who assists with credentials, funding, or transport + +## Safe Patterns + +- one actor owns all roles +- delegated uploader acts for the payer, but the payload still proves author +- helper service never invents or rewrites anchor outputs + +## Unsafe Patterns + +- payer identity used as a proxy for authorship +- unsigned payloads later treated as provenance-bearing records +- stale `pieceCid` / timestamp / dataset fields carried forward to new records +- helper outage breaking the core protocol path + +## Review Test + +Ask, in order: + +1. Who produced the exact uploaded bytes? +2. Who signed them? +3. Who paid? +4. Who published the pointer? +5. Can any other process rewrite those answers later? + +If the answers drift across systems, the authority boundary is probably wrong. diff --git a/skills/foc-platform/references/use-cases/durable-state.md b/skills/foc-platform/references/use-cases/durable-state.md new file mode 100644 index 0000000..9a624cc --- /dev/null +++ b/skills/foc-platform/references/use-cases/durable-state.md @@ -0,0 +1,38 @@ +--- +description: Durable-state and signed-record anchoring patterns on Filecoin Onchain Cloud. +--- + +# Durable State + +Use this when the uploaded bytes are more than files: signed reports, audit +records, manifests, local app state, or other data whose authorship matters. + +## Correct Order + +1. Produce canonical bytes at the authority that owns the state. +2. Compute the local hash / root over those bytes. +3. Sign the bytes or a deterministic envelope containing the root. +4. Upload to Filecoin. +5. Persist the real anchor outputs: + `pieceCid`, `providerId`, `dataSetId`, `pieceId`, anchor timestamp. +6. Publish external pointers or manifests. + +## Never Do + +- publish the pointer first, fill storage fields later +- let a helper service invent the state hash after the fact +- infer authorship from the payer wallet +- treat PDP as a signature system + +## Role Split + +Valid: + +- author = uploader = signer +- author != payer, but the uploaded payload contains the author's signature +- helper only issues credentials, funding, or transport assistance + +Invalid: + +- helper uploads unsigned state and claims the state is user-authored +- one process computes the pointer, another later patches in storage IDs diff --git a/skills/foc-platform/references/use-cases/public-content.md b/skills/foc-platform/references/use-cases/public-content.md new file mode 100644 index 0000000..d90b020 --- /dev/null +++ b/skills/foc-platform/references/use-cases/public-content.md @@ -0,0 +1,34 @@ +--- +description: Public-content patterns combining IPFS indexing and Beam/CDN. +--- + +# Public Content + +## Use IPFS Indexing When + +- content should resolve by IPFS root CID +- public gateways or IPNI discovery matter +- the uploaded bytes are CAR / IPLD-friendly content + +Pattern: + +- dataset metadata includes `withIPFSIndexing` +- piece metadata includes `ipfsRootCID` +- verify gateway/IPNI visibility before claiming public availability + +## Use Beam / CDN When + +- low-latency retrieval matters +- traffic volume justifies egress costs +- public discovery is not enough on its own + +## Do Not Conflate + +- IPFS indexing: + discoverability / addressing +- Beam / CDN: + retrieval performance / egress path +- PDP: + storage possession proof +- payload signature: + authorship / provenance diff --git a/skills/synapse-sdk/SKILL.md b/skills/synapse-sdk/SKILL.md new file mode 100644 index 0000000..48f346b --- /dev/null +++ b/skills/synapse-sdk/SKILL.md @@ -0,0 +1,49 @@ +--- +name: synapse-sdk +description: Use when integrating, upgrading, debugging, or operating @filoz/synapse-sdk / @filoz/synapse-core for Filecoin Onchain Cloud storage, session keys, multi-copy uploads, dataset reuse, provider routing, or PDP-backed retrieval. +--- + +# synapse-sdk + +Use this for current 2026 Synapse work. Treat pre-viem, pre-0.37, or +pre-`source` examples as migration material, not default guidance. + +## Hard Rules + +- Prefer current truth in this order: + `references/core/source-ledger.md` +- Default to `Synapse.create({...})`. +- Use `new Synapse({ client, sessionClient? })` only when a wallet client + already exists. +- Pass a deliberate `source`; stable non-empty string is default, `null` only + when shared namespace reuse is intentional. +- Call `prepare()` before first upload, large upload, or storage-setting change. +- `upload()` is partial-success: returned result means at least one committed + copy; `complete === true` means all requested copies succeeded. +- Dataset metadata is low-cardinality routing state. Piece metadata is + object-specific state. +- Session keys must have synced expirations before client construction. +- PDP proves possession, not authorship; sign uploaded bytes when authenticity + matters. + +## Fast Path + +1. Current versions, limits, chains, cost knobs: + `references/core/facts.md` +2. Default upload/download and split flows: + `references/use-cases/flows.md` +3. Delegated signing: + `references/use-cases/session-keys.md` +4. Funding, partial copies, metadata surprises: + `references/debugging/failures.md` +5. Namespace, dataset explosion, provenance pitfalls: + `references/edge-cases/namespaces.md` + +## References + +- `references/core/facts.md` +- `references/core/source-ledger.md` +- `references/use-cases/flows.md` +- `references/use-cases/session-keys.md` +- `references/debugging/failures.md` +- `references/edge-cases/namespaces.md` diff --git a/skills/synapse-sdk/references/core/facts.md b/skills/synapse-sdk/references/core/facts.md new file mode 100644 index 0000000..e1c9601 --- /dev/null +++ b/skills/synapse-sdk/references/core/facts.md @@ -0,0 +1,51 @@ +--- +description: Verified March 23, 2026 facts for current Synapse SDK work. +--- + +# Facts + +Verified `2026-03-23`. + +- npm latest: + - `@filoz/synapse-sdk` = `0.40.0` + - `@filoz/synapse-core` = `0.3.1` +- Public baseline: + - Node.js `20+` + - `viem` peer dependency `2.x` +- Preferred constructor: + - `Synapse.create({ account, source, chain?, transport?, withCDN?, sessionKey? })` +- Advanced constructor: + - `new Synapse({ client, source, withCDN?, sessionClient? })` +- Default upload copies: `2` +- Upload result shape: + - `requestedCopies` + - `complete` + - `copies[]` + - `failedAttempts[]` +- Size limits: + - min `127` bytes + - max `1,065,353,216` bytes +- Metadata limits: + - dataset metadata: `10` pairs + - piece metadata: `5` pairs +- Time model: + - epoch = `30s` + - day = `2880` epochs + - month = `86400` epochs + - default lockup = `30` days +- Chain ids: + - mainnet: `314` + - calibration: `314159` + - devnet: `31415926` +- Current storage economics: + - storage = `2.50 USDFC / TiB / 30-day month` + - minimum rate = `0.06 USDFC / month / dataset` + - new dataset sybil fee = `0.1 USDFC` + - CDN fixed lockup = `1.0 USDFC` per new CDN dataset + +Operational implications: + +- `prepare()` is the default funding gate. +- `source` participates in dataset reuse. +- `failedAttempts.length > 0` is diagnostic only. +- Persist committed copy info, not just `pieceCid`. diff --git a/skills/synapse-sdk/references/core/source-ledger.md b/skills/synapse-sdk/references/core/source-ledger.md new file mode 100644 index 0000000..39788d8 --- /dev/null +++ b/skills/synapse-sdk/references/core/source-ledger.md @@ -0,0 +1,41 @@ +--- +description: Official source order and conflict handling for Synapse SDK facts. +--- + +# Source Ledger + +Verified `2026-03-23`. + +## Source Order + +1. npm registry metadata + - `https://registry.npmjs.org/@filoz/synapse-sdk` + - `https://registry.npmjs.org/@filoz/synapse-core` +2. Current GitHub source and changelogs + - `https://github.com/FilOzone/synapse-sdk` +3. Official docs + - `https://docs.filecoin.cloud/getting-started/` + - `https://docs.filecoin.cloud/developer-guides/storage/storage-operations/` + - `https://docs.filecoin.cloud/developer-guides/storage/storage-context/` + - `https://docs.filecoin.cloud/developer-guides/storage/storage-costs/` + - `https://docs.filecoin.cloud/developer-guides/session-keys/` + - `https://docs.filecoin.cloud/developer-guides/migration-guide/` +4. Official example app + - `https://github.com/FIL-Builders/fs-upload-dapp` + +## Conflict Rules + +- Release numbers and publish dates: npm wins. +- API shape and exported names: current GitHub source wins. +- Product guidance and economics: current docs win unless contradicted by newer + source. +- Examples are illustrative, not normative. + +## Known Drift To Normalize + +- Examples using `new Synapse({ client, ... })` are valid advanced patterns, not + the default starting point. +- Any `Synapse.create()` example without `source` is stale for current typings; + use a stable non-empty string or explicit `null`. +- `warmStorageAddress` is not a modern `Synapse.create()` option; address + discovery is internal for supported chains. diff --git a/skills/synapse-sdk/references/debugging/failures.md b/skills/synapse-sdk/references/debugging/failures.md new file mode 100644 index 0000000..008729e --- /dev/null +++ b/skills/synapse-sdk/references/debugging/failures.md @@ -0,0 +1,76 @@ +--- +description: Failure classification and recovery rules for Synapse SDK operations. +--- + +# Failures + +Classify before changing code. + +## Funding Or Approval + +Signals: + +- `prepare()` returns `transaction` +- uploads fail on underfunded accounts +- new datasets stop progressing + +Check: + +- `prep.costs.depositNeeded` +- `prep.costs.needsFwssMaxApproval` +- whether the app skipped `prepare()` + +## Session Key + +Signals: + +- root wallet works, delegated path fails +- things work immediately after login, then stop later + +Check: + +- permission set +- `sessionKey.syncExpirations()` +- whether the client was constructed before expirations were refreshed + +## Metadata / Reuse + +Signals: + +- new dataset every upload +- wrong dataset reused +- expected prior dataset missing + +Check: + +- exact dataset metadata keys and values +- `source` +- `withCDN` +- `withIPFSIndexing` +- any volatile keys in dataset metadata + +## Provider / Copy Path + +Signals: + +- returned result but `complete === false` +- fewer copies than requested +- secondaries fail while primary succeeds + +Check: + +- `result.copies.length` +- `result.requestedCopies` +- `result.failedAttempts` +- whether split flow is needed for observability or recovery + +## Error Meaning + +- `StoreError`: zero providers committed anything; retry upload +- `CommitError`: bytes were stored but all commits failed; retry commit path +- returned result + non-empty `failedAttempts`: not necessarily failure + +## Drift + +If docs, examples, and code disagree, normalize with +`references/core/source-ledger.md`. diff --git a/skills/synapse-sdk/references/edge-cases/namespaces.md b/skills/synapse-sdk/references/edge-cases/namespaces.md new file mode 100644 index 0000000..240eba4 --- /dev/null +++ b/skills/synapse-sdk/references/edge-cases/namespaces.md @@ -0,0 +1,43 @@ +--- +description: Namespace isolation, metadata discipline, and provenance edge cases. +--- + +# Namespaces + +## Reuse Is Exact + +- Dataset reuse requires exact metadata key/value equality. +- Adding or removing one dataset key creates a new reuse namespace. +- `source` is part of that namespace. + +## Stable vs Volatile + +Good dataset metadata: + +- environment +- collection +- schema +- product/domain + +Bad dataset metadata: + +- timestamps +- run ids +- user/session ids +- random UUIDs + +Keep volatile identifiers in piece metadata or inside the payload. + +## Reserved Meanings + +- `withCDN`: dataset-level retrieval addon request +- `withIPFSIndexing`: dataset-level IPNI/IPFS indexing request +- `ipfsRootCID`: piece-level advisory root CID +- `source`: dataset namespace isolation key + +## Provenance + +- PDP proves the bytes are held. +- PDP does not prove who authored the bytes. +- Payer identity does not prove content authorship. +- If provenance matters, upload a signed envelope or signed canonical payload. diff --git a/skills/synapse-sdk/references/use-cases/flows.md b/skills/synapse-sdk/references/use-cases/flows.md new file mode 100644 index 0000000..b451131 --- /dev/null +++ b/skills/synapse-sdk/references/use-cases/flows.md @@ -0,0 +1,65 @@ +--- +description: Golden-path and split-path Synapse SDK workflows. +--- + +# Flows + +## Golden Path + +```ts +const synapse = Synapse.create({ account, chain, source: "my-app" }) + +const prep = await synapse.storage.prepare({ + dataSize: BigInt(data.byteLength), +}) +if (prep.transaction) await prep.transaction.execute() + +const result = await synapse.storage.upload(data, { + copies: 2, + metadata: dataSetMetadata, + pieceMetadata, +}) + +if (!result.complete) { + // Partial success: use copies[], inspect failedAttempts[] +} +``` + +Use this when: + +- default provider selection is acceptable +- one call is more important than per-provider control +- retrying from raw bytes is fine + +## Split Flow + +Use for batch uploads, multi-file orchestration, explicit per-provider progress, +or commit retries without re-uploading bytes. + +1. `createContexts({ copies, metadata })` +2. `primary.store(data)` +3. `secondary.presignForCommit([{ pieceCid, pieceMetadata? }])` +4. `secondary.pull({ pieces, from: primary.getPieceUrl, extraData })` +5. `commit()` only on contexts that actually hold the piece +6. Persist `providerId`, `dataSetId`, `pieceId`, `retrievalUrl`, `role` + +Rules: + +- Pre-sign once, reuse `extraData` for `pull()` and `commit()`. +- Primary is client upload. Secondaries are SP-to-SP transfer. +- `CommitError` after successful store/pull means retry commit, not re-upload. + +## Downloads + +- Default: + `await synapse.storage.download({ pieceCid, withCDN? })` +- Explicit provider path: + use `context.getPieceUrl(pieceCid)` when you need provider-specific retrieval + or your own fetch pipeline. + +## Metadata Split + +- dataset metadata: + stable, low-cardinality, reuse-driving +- piece metadata: + per-object, high-cardinality, advisory diff --git a/skills/synapse-sdk/references/use-cases/session-keys.md b/skills/synapse-sdk/references/use-cases/session-keys.md new file mode 100644 index 0000000..505b083 --- /dev/null +++ b/skills/synapse-sdk/references/use-cases/session-keys.md @@ -0,0 +1,51 @@ +--- +description: Current delegated-signing flow for Synapse SDK session keys. +--- + +# Session Keys + +## Default Flow + +```ts +import * as SessionKey from "@filoz/synapse-core/session-key" + +const sessionKey = SessionKey.fromSecp256k1({ + privateKey, + root: rootAccount, + chain, +}) + +await SessionKey.loginSync(rootWalletClient, { + address: sessionKey.address, +}) + +await sessionKey.syncExpirations() + +const synapse = Synapse.create({ + account: rootAccount, + chain, + source: "my-app", + sessionKey, +}) +``` + +## Default FWSS Permissions + +- `CreateDataSetPermission` +- `AddPiecesPermission` +- `SchedulePieceRemovalsPermission` +- `DeleteDataSetPermission` + +## Use Session Keys When + +- wallet popups would otherwise dominate UX +- repeated storage operations must happen in-browser or on-device +- uploads must keep root ownership while delegating short-lived signing + +## Hard Rules + +- `syncExpirations()` before constructing `Synapse`. +- Missing or expired permissions fail like contract/auth errors, not random + provider errors. +- Session keys delegate signing, not authorship. +- If payer and content author differ, prove authorship inside the payload.