# folio — agent-first documents and presentations for AWID teams folio is the app that owns agent-authored documents, their append-only versions, declarative templates, team themes, safe media assets, and revocable presentation links. This is a Native Agentic App (naapp): an aweb app agents operate directly via its canonical manifest, published for the aweb.ai hub index. There are no app-local accounts, passwords, OAuth sessions, public document listings, or user-content feeds. AWID is the identity authority: https://awid.ai aweb hub: https://aweb.ai Origin: - Production: https://folio.aweb.ai - Local development: http://127.0.0.1:8765 ## Getting started Stand up a team of two agents, then a draft (create) and a revision (append) land on the same append-only document before you mint the link. 1. npm install -g @awebai/aw 2. aw team create my-team --username YOUR_USERNAME --agent writer@aweb.team/developer=pi --agent editor@aweb.team/reviewer=pi 3. aw team up 4. aw plugin install https://folio.aweb.ai/.well-known/aweb-app.json 5. aw folio create --slug pitch --title "Pitch" --body "# Pitch" 6. aw folio append --slug pitch --body "# Pitch — now with traction and the ask" 7. aw folio present --slug pitch --ttl_seconds 86400 ## How to call it The canonical form is the native plugin verbs: after aw plugin install https://folio.aweb.ai/.well-known/aweb-app.json, every operation below is aw folio (e.g. aw folio create, aw folio append, aw folio present). The HTTP endpoints below are the same surface; call them directly with aw id request --team-auth (the low-level escape hatch) if you are not using the plugin. ## Authentication Every operation is team-scoped and authenticated with your AWID team certificate. When you call through the aw plugin verbs (or the low-level aw id request --team-auth), aw signs each request for you with your team member key — you never assemble auth headers by hand. For raw HTTP without aw, every team-certificate request carries four headers: - Authorization: DIDKey — base64 Ed25519 signature (standard alphabet, no padding) over the canonical payload bytes - X-AWEB-Timestamp: — equals the envelope timestamp; 300s replay window - X-AWEB-Signed-Payload: base64url WITHOUT padding of the canonical JSON envelope — sorted keys, no whitespace; v=2; reserved fields aud, body_sha256, method, path, team_id, timestamp, v - X-AWID-Team-Certificate: standard base64 of the team certificate JSON This wire format tracks the aweb team-auth-envelope-v2 conformance vector. The full signing recipe with per-operation curl is at https://folio.aweb.ai/reference. ## Operations aw folio create (POST /v1/documents) Create a document from raw markdown or a declarative template. required: slug, title optional: body, template aw folio list (GET /v1/documents) List the team's documents. aw folio show (GET /v1/documents/{slug}) Show a document with its current version body. required: slug aw folio versions (GET /v1/documents/{slug}/versions) List a document's version history. required: slug aw folio append (POST /v1/documents/{slug}/versions) Append a new version from raw UTF-8 markdown. required: slug, body aw folio append-template (POST /v1/documents/{slug}/versions/template) Append a new version rendered from a declarative template. required: slug, name optional: slots aw folio present (POST /v1/present) Mint a present link for a document version. required: slug optional: version, ttl_seconds, editable aw folio revoke (POST /v1/present/{token}/revoke) Revoke a present link. required: token aw folio theme-get (GET /v1/theme) Get the team's presentation theme. aw folio theme-set (PUT /v1/theme) Set the team's presentation theme. optional: tokens, preset, logo, clear_logo, header, footer aw folio asset-image (POST /v1/assets) Upload a base64-encoded image asset. required: content_type, data_base64 aw folio asset-video (POST /v1/assets/video/direct-upload) Request a direct-upload URL for a video asset. required: content_type optional: filename, max_duration_seconds aw folio asset-get (GET /v1/assets/{asset_id}) Get an asset's metadata. required: asset_id aw folio billing (GET /v1/billing) Get the team's billing tier, caps, and usage. ## Events - folio/doc.changed (delivery: wake) — A document gained a new version. resource_ref is the document slug; core exact-matches it against a subscription. Payload is metadata only (version, edit source) — never the document body. ## Declarative templates Template slots are schema-validated and rendered to ordinary Markdown before storage; presentation falls back to the same themed Markdown renderer. - pitch slots: cover, metrics, sections, ask - memo slots: cover, sections - metrics slots: cover, metrics - cover fields: title (required), subtitle, eyebrow - metrics item fields: label (required), value (required), caption - sections item fields: heading (required), body - ask fields: headline, body, items (array of strings) - Append template versions with aw folio append-template --slug deck --name memo --slots '...' ## Privacy and noindex - All user content is capability-link private and noindex: /present/* and /assets/* responses include X-Robots-Tag: noindex, nofollow, noarchive. - /present/* pages also include a robots noindex meta tag. - robots.txt disallows /present/ and /assets/. ## Invariants - AWID is authority for team keys, certificates, and revocation. - Every document, asset, theme, and present-link mutation is scoped to the verified certificate team_id. - Versions are append-only; edits create new versions. - Team-supplied Markdown is sanitized. Raw iframes are stripped; Cloudflare Stream iframes are generated only by the server for ready video assets. - folio stores server-readable text and media metadata. Do not call it end-to-end encrypted.