Documentation Index
Fetch the complete documentation index at: https://docs.kynesys.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Access Control
Every Storage Program carries aStorageProgramACL that the node consults on every read, write, and delete. This guide covers the ACL data model, the resolution priority the node uses to grant or deny a request, each of the three modes, and how to mutate the ACL after deployment.
This page assumes you already have a connected demos instance and an ownerAddress. If not, start with Getting Started.
The ACL data model
The ACL lives on the program payload asacl and is fully typed in @kynesyslabs/demosdk:
- The owner of a program (the
deployerAddresspassed tocreateStorageProgram) always has full access. They are not listed inallowedand cannot be put onblacklisted. modeis the only required field. The other three (allowed,blacklisted,groups) are independent and can be combined freely.- If you omit
aclentirely oncreateStorageProgram, the SDK fills in{ mode: "owner" }.
Resolution priority
The node walks the ACL in this exact order on every operation. The first rule that matches wins.- Owner — the program’s deployer always has FULL ACCESS (read, write, delete).
- Blacklisted — if the requester is in
blacklisted, the request is DENIED, even if they also appear inallowedor in a group. - Allowed — if the requester is in
allowed, the requested permission is granted. - Groups — each group is checked; if the requester is a member of a group whose
permissionsinclude the requested action, it’s granted. - Mode fallback — when nothing above matches:
owner→ DENIEDpublic→ READ-only (write and delete are denied)restricted→ DENIED
blacklisted strictly stronger than allowed and groups, and what makes public a true “anyone can read” default without needing to list every reader.
Mode reference
All three modes use the same payload-builder flow described in Getting Started: build the payload,demos.storagePrograms.sign(payload), demos.confirm(tx), then demos.broadcast(validityData).
Owner mode
Default mode. Only the program’s owner can read, write, or delete. Use it for personal data you never intend to share.Public mode
Anyone can read. Only the owner can write or delete. Use it for announcements, profiles, indexes, or anything you want to publish openly.public only relaxes reads.
Restricted mode
Reads, writes, and deletes are denied by default. Access is granted only through explicitallowed entries or groups. Use it for team workspaces, multi-tenant data, or any non-public dataset with a known set of collaborators.
{ mode: "restricted" } with no allowed and no groups is identical to owner mode — only the deployer gets through.
allowed and blacklisted
These two lists are independent of mode and can be combined with any mode.
allowedgrants the listed addresses all permissions (read, write, delete).blacklisteddenies the listed addresses every permission, no matter whatmode,allowed, orgroupssay. It is checked beforeallowedand groups, so blacklisting always wins.
The owner cannot be denied. Putting the owner’s address in
blacklisted has no effect — rule 1 (owner = full access) is checked before rule 2.Groups
Groups let you express role-based access without flattening every member into a singleallowed list. Each group has a members array and a permissions array drawn from "read", "write", and "delete".
- The owner can do anything (rule 1).
- Alice and Bob can read and write but not delete.
- Carol and Dave can read.
- Anyone else falls through to the
restrictedmode fallback and is denied.
blacklisted still overrides every group membership.
Mutating the ACL after creation
UseStorageProgram.updateAccessControl(storageAddress, acl) to replace the ACL on an existing program. Only the program’s owner can submit this transaction — any other signer is rejected at the node.
acl argument is the new ACL in full — the node replaces the stored ACL with what you send. To add a member to a group, read the current ACL, mutate the groups map, and submit the whole object back:
- The owner of a program is set at creation time and cannot be changed via
updateAccessControl. Ownership is permanent. updateAccessControlis a regular Storage Program transaction — it incurs the same per-chunk fee as any other write. See Getting Started → Fees.- The new ACL takes effect once the transaction is included in a block. In-flight reads against the previous ACL may still succeed until the new state is committed.
Quick decision guide
| You want… | Use |
|---|---|
| Personal data only you can touch | mode: "owner" |
| Open read, owner-only writes | mode: "public" |
| A small fixed set of collaborators | mode: "restricted" + allowed |
| Different roles with different permissions | mode: "restricted" + groups |
| Block known-bad addresses | any mode + blacklisted |
| Open to all readers but tightened for writes | mode: "public" (writes are owner-only by definition) |
Convenience helpers
The SDK exposes a few static helpers onStorageProgram that return prebuilt ACL objects so you don’t have to spell them out:
StorageProgramACL you can pass straight into createStorageProgram or updateAccessControl.
Programmatic permission checks
If you want to predict whether a given address would be granted a permission against a given ACL — for example, to gate UI elements before submitting a transaction — useStorageProgram.checkPermission:
Legacy access control (deprecated)
Before v3.1.0, programs used a single string fieldaccessControl: "private" | "public" | "restricted" | "deployer-only" plus a top-level allowedAddresses array. That shape is deprecated and only kept on StorageProgramPayload for backward compatibility with old clients. New code should always use acl.
The mapping if you’re migrating older payloads:
Legacy accessControl | New acl.mode |
|---|---|
"private" | "owner" |
"deployer-only" | "owner" |
"public" | "public" |
"restricted" | "restricted" (move allowedAddresses into acl.allowed) |
StorageProgram.createStorageProgramLegacy and StorageProgram.updateAccessControlLegacy for that legacy shape, both marked @deprecated. Don’t call them in new code — the new acl form is strictly more expressive and is the only one that supports blacklisted and groups.
Where to go next
- Operations — full lifecycle of a Storage Program (create, write, granular updates, delete) and how the ACL applies at each step.
- RPC Queries — passing a requester identity to ACL-gated reads and listing programs by owner.
- API Reference — every
StorageProgramstatic helper, payload shape, and response type. - Cookbook — end-to-end recipes including team workspaces and public profiles.