About bounded-backend
A backend policy authoring skill for Bounded apps, covering rules, invariants, functions, actor identity, and policy tests. It is intended for developers building or maintaining Bounded backends and routes them to task-specific references.
Key features
- 01Write access rules and runtime invariants
- 02Define functions, identity, and authorization
- 03Consult policy examples and access patterns
- 04Run concrete policy tests and inspect failures
- 05Route tasks to relevant backend references
Use cases
- 01Set ownership and membership access rules
- 02Constrain balances, supply, or tenant data
- 03Configure function identity, authorization, and invocation
- 04Test which operations policies allow or deny
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ bounded-sh/ skill --skill bounded-backendAfter installing, type/bounded-backendin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
docs/access-control.mdaccess-patterns.mdadmin-and-ownership.mdagents-flue.mdai-npcs.mdbackend-runtime.mdbrowser-boundary.mdbuilding-a-backend.mdbuilding-for-agents.mdconstants-and-defs.mddata-plane.mdexamples.mdfiles-and-search.mdformal-verification.mdfunctions-ctx-ai.mdfunctions-ctx-browser.mdfunctions-ctx-build.mdfunctions-ctx-enqueue.mdfunctions-ctx-services.mdfunctions-graduation.mdfunctions-when-to-use.mdfunctions.mdhooks-and-anti-cheat.mdhooks-scheduled-webhooks.mdidentity-and-logs.mdinvariants.mdlive-runtime.mdpolicy-cheat-sheet.mdpolicy-examples.mddocs/examples/marketplace.mdDetails
From the project READMEBounded backend
The server side of a Bounded app: the policy that governs documented supported
mutation surfaces, the runtime-enforced invariants, the functions that run
trusted code, and the actor model that decides who is acting.
bounded deploy validates, compiles, and pushes; runtime rule and invariant
checks reject violations before commit on their documented supported mutation
surfaces. Check a policy with concrete policy tests (bounded tests run) and by
deploying it. Do not generalize that coverage to an unsupported plane,
undocumented storage path, or inherited corpus. For CLI/deploy see the
bounded-deploy skill; for the client SDK and auth UI see
bounded-frontend; to route across the family, see the root bounded skill.
Write the actor model in mind from the start: know who @user is, which principal
a function acts as (runAs/actAs), and where authorization comes from
(@origin) before you write a rule.
Reference Router
Building one of the five most common app shapes? Take the quick path - one target page per build - instead of scanning this table. Otherwise read only the row matching the current task or term.
| Task or term | Read |
|---|---|
| One-screen syntax: field types, tiers, variables, operators, where logic goes | policy cheat sheet |
| Generate or repair a policy from an app description | policy generation |
| Complete policy examples by intent (marketplace, escrow, vaults, staking, tokens, ...) | examples index |
| Worked multi-collection policies (team SaaS, marketplace, realtime game) | examples |
| Rule recipes: owner-only, admin-or-owner, membership, time windows, validation, immutable fields, atomic batches | access patterns |
Require or copy a user's verified X account in a rule, get(/__connections__/@user.id).xHandle, testing linked-X rules, handles typed before linking, onchain apps | connected accounts |
Rules, fields, expressions, @user, @data, @newData, @time, get(), getAfter(), ownership fields | policy reference |
Caps, balances, supply, tenant isolation, hard bounds; rollingSum, windowSum, flowBound, conserve, tenantTag, tenantEdge, bound | invariants |
Trending feeds, leaderboards, ranked windowSum reads | trending feeds |
| Browser CSP / restrict what app pages may reach | browser boundary |
Constants, reusable rules, @const, @def | constants and defs |
| Choose rule vs invariant vs hook vs function | when to use functions |
Functions; declare, auth, entry, secrets, actAs, ctx.user, ctx.bounded, ctx.env, ctx.secrets, invoke, deploy | functions |
Public functions: HTTP routes without a Bounded session at <slug>-api.bounded.page, public, methods, cors, public JWKS, machine callers, webhook and browser-public modes | public functions |
ctx.ai.run, ctx.ai.generateImage, ctx.ai.generateVideo, getJob, AI without API keys | ctx.ai |
ctx.services, managed third-party APIs, bounded services | ctx.services |
ctx.browser, headless browser from a function, driving your own app signed in, @const.AGENT, agent identity | ctx.browser |
ctx.enqueue, background jobs, queues, replay identity | ctx.enqueue |
ctx.build, functions that originate governed app builds, image and video builds, mediaSlots | ctx.build |
| Start simple and graduate to functions | function graduation |
| User-owned provider API keys | secrets |
Schedules, dueRows, hooks, webhooks, verifyWebhook | scheduled hooks and webhooks |
| Recurring fleet sweeps without full scans | scheduled sweeps |
| Anti-cheat proof limits | hooks and anti-cheat |
Atomic writes, subset attacks, requiresInBatch, incomplete_batch | data plane |
Queries, pagination, queryAggregate, count, filters, missing versus null, $exists, sort, cursor | queries |
Files, setFile, storage, full-text search | files and search |
Realtime rooms; session.tick, settleTo, settleFrom, fog-of-war views | realtime and games |
Native live modules; session.live, tick, views, @effect, live.intent | live runtime |
| Input cadence, interpolation, prediction | realtime netcode |
| AI NPCs / AI players | AI NPCs |
| Long-running backend runtime or managed services | backend runtime |
| Multi-step Flue agents | Flue agents |
| Owners, collaborators, scoped admins | admin and ownership |
Top-level roles, members, read:"*", read/write scopes | roles |
access, custom/external roles, __owners__, __admins__, __developers__, __viewers__ | access control · identity and logs |
Service keys, payout bots, backend identities, runAs, actAs, @origin, ctx.origin | service keys · principals and origins |
Concrete allow/deny tests; policy-tests/*.json, bounded tests run/push/list/pull | policy tests |
| End-to-end tests for authenticated apps | testing authed apps |
| Completion review | quality checklist |
| Agent-facing or backend-only app | building for agents · building a backend |
Error Router
| Error/status | Meaning |
|---|---|
403 | A write or function invoke failed a rule. Check auth, ownership, roles, or function auth. Denied reads are hidden as 200 with empty data, not 403. |
500 rule_evaluation_failed | The rule was reached and could NOT be evaluated - no rule denied you, and nothing was read or written. Not a denial, not a retryable conflict. Read bounded decisions for the cause; the row is recorded with decision: error. |
409 + invariant name | The transaction would violate an invariant. Fix state or policy. |
403 incomplete_batch | A collection's requiresInBatch declaration names companion paths missing from the atomic batch. Submit the complete setMany. |
| Deploy validation error | Deploy refused the policy before anything changed. Fix policy syntax, field types, tier/invariant pairing, constants, or expression use as the message names. |
Rules Of Thumb
-
Use
@user.idfor normal ownership and membership checks;@user.addressonly for wallet/onchain semantics. -
Denied reads return empty
200responses.get()inside a policy-testexpectreads sandbox state with read rules skipped, so prove a denied read with a second real session. Write and delete denials stay onshouldFail. -
Use
conservefor fixed totals,rollingSumfor caps over time, andflowBoundfor cumulative per-partition outflow ≤ inflow; use one atomicset-manywhen correctness spans multiple writes. -
When one write is invalid without companion writes, declare
requiresInBatchso a hostile client cannot submit only the individually valid subset. -
Put provider API keys in Bounded secrets, not frontend code.
-
Know the acting principal before writing a rule: a function's
runAs/actAsand@origindecide who@useris and whether the call is authorized. -
For authenticated app actions, use the client SDK
functions.invoke, declare the function auth rule, and usectx.user. Do not send a Bounded session token in function arguments or build a JWT verifier inside a public HTTP function. Keep intentionally public data, such as today's prompt, in a separate public function without user-state access. -
Verify private function flows as a non-owner user, including an anonymous session when the app supports guests. Save state, reload, and resume it; owner CLI calls can mask data-read permission failures. A denied read may appear as missing data, so investigate authorization before recreating state or weakening rules.