| name | pinning-to-freeside |
| description | Upload metadata JSON and image assets to Freeside (Honey Jar's own infra) and return immutable URIs. Vendor implementation for the primary pin under the dual-pin policy. |
| user-invocable | true |
| allowed-tools | Read, Write, Edit, Bash |
Pinning to Freeside
Vendor implementation for the primary pin in the-orchard's dual-pin policy. Freeside-first because we control the operational continuity (mibera incident lesson: external services go down).
Vocabulary note. "Freeside" in the-orchard's vocabulary is the role — Honey Jar's first-party storage soil. The backend impl today is thj-assets S3 + CloudFront (d163aeqznbc6js.cloudfront.net); Freeside proper is the billing/settlement layer (per loa-dixie/knowledge/sources/freeside-api-reference.md). The skill name is preserved because Freeside-as-soil is operator vocabulary; the FreesideClient interface is vendor-agnostic, so when a true Freeside metadata API lands the swap is one impl deep. Configure backend via FREESIDE_BACKEND env (default: thj-assets).
Trigger
/tend storage --pin freeside <token-id>
"pin to freeside"
"upload to honeyjar infra"
When to use
- Called by
tending-storage during a dual-pin pass (default path)
- Called by
migrating-storage when lifting tokens off a defunct external service
- One-shot pin requested by operator (rare — usually you want the orchestrated pass)
When NOT to use
- Freeside endpoint is not configured (
FREESIDE_API_URL env unset) — refuse, surface configuration gap
- Token does not yet exist on-chain —
the-mint + protocol first, then tend
- Operator wants IPFS-only — sibling
pinning-to-ipfs
Workflow
-
Validate input. Required: tokenId, collection, metadata (JSON), image (path or buffer). Optional: imageHash (sha256, computed if omitted).
-
Resolve backend. Read FREESIDE_BACKEND env: one of thj-assets (default — S3 + CloudFront), freeside-api (future), or operator-extension. Each backend implements the same FreesideClient interface. Auth credentials per backend (AWS_ACCESS_KEY_ID_VM + AWS_SECRET_ACCESS_KEY_VM for thj-assets; FREESIDE_API_KEY for freeside-api). If credentials missing, refuse and emit configuration Verdict (severity: high, blocks the dual-pin pass).
-
Upload image first. Send image bytes via the configured backend. For thj-assets: PUT to s3://thj-assets/{collection}/migrated/{tokenId}.{ext} with CacheControl: public, max-age=31536000, immutable; receive { url, hash } where url is ${THJ_CDN_BASE}/{collection}/migrated/{tokenId}.{ext} (default CDN base: https://d163aeqznbc6js.cloudfront.net). Verify hash matches local imageHash.
-
Substitute image URL into metadata. Replace any placeholder image: field in the metadata JSON with the freeside URL from step 3.
-
Upload metadata. Send the JSON body via the configured backend. For thj-assets: PUT to s3://thj-assets/{collection}/migrated/{tokenId}.json with Content-Type: application/json. Receive { url, hash }.
-
Return URI. The returned url is the freeside metadata URL — what gets recorded in pins/{collection}.yaml as freeside_url and (eventually) becomes the token's on-chain tokenURI after a protocol call.
Output shape
interface FreesidePinResult {
tokenId: number
collection: string
freeside_url: string
metadata_hash: string
image_url: string
image_hash: string
pinned_at: string
}
Anti-patterns
- Trusting the upload response without hash verification. A successful HTTP 200 means the request landed; hash verification means the bytes match. Always verify.
- Pinning the metadata before the image. Metadata references the image URL. If you pin metadata first, the image URL is a placeholder — the metadata is then immediately stale. Image first, always.
- Hardcoding backend URLs. Environment-configured (
THJ_CDN_BASE, FREESIDE_API_URL, etc., per backend). Honey Jar may stand up regional or production-vs-staging endpoints later, or migrate the backend entirely.
- Treating Freeside like a vendor. It's the soil. Don't speak about it like AWS S3 in operator-facing output — even though S3 is what powers it today.
- Hard-coupling to one backend. The
FreesideClient interface is vendor-agnostic. If you write code that assumes thj-assets path conventions inside another skill, you've broken the interface. Always go through the skill.
Composes with
- Called by:
tending-storage (orchestrator) · migrating-storage (recovery path) · updating-metadata and updating-image (graft re-pin)
- Sibling:
pinning-to-ipfs (the dual-pin partner; both run for every pinnable token)
- Validates with:
verifying-pin runs after to confirm resolution
Voice
Direct, terse, hash-aware. Burbank's voice through this skill is the cultivator confirming the soil amendment landed: "Image up, hash matches. Metadata up, hash matches. Freeside has it. Now IPFS."