Permission Model
NOOSChain is a permissioned system. Actions are performed by known actors, and bucket access is granted to explicit principals.
The permission model has two layers:
- Actor resolution answers: who is performing this action?
- Bucket permissions answer: what is that actor allowed to do to this bucket?
Permissions are consensus-state rules. API checks improve read security and error messages, but deterministic block execution is authoritative.
Actors And Principals
An actor is the resolved identity performing an operation.
A principal is an identity that can be named in a bucket access rule.
Most of the time they line up, but the distinction matters for contracts and organizations. A signed user transaction resolves to a user actor; that user may also receive permissions through an organization principal. A smart contract call resolves to a contract actor during contract execution; the contract must have its own bucket access rule for sensitive bucket host calls.
System Actor
GENESIS and system execution can perform genesis/system operations. These paths are special and should not be treated as ordinary user authorization.
Normal application and operator workflows should use signed transactions from registered users.
Users
Users are identity-bearing actors with public keys. Execution derives authority from transaction.envelope.signerPublicKey, not from untrusted payload fields.
The signer public key maps deterministically to a user. That user's organization comes from chain state.
For non-system bucket creation and encrypted-record writes, creator fields in the payload must match the resolved signer user and organization.
Organizations
Organizations group users and can receive bucket permissions as principals.
An organization bucket access rule applies to every actor in that organization. For example, granting bucket:read_metadata to organization org-noos allows users in org-noos to read bucket and record metadata.
Organization membership also matters for bucket-key envelope recipient selection and for node replication policies.
Nodes
Nodes run NOOSChain software. Validator nodes participate in consensus; observer nodes sync and serve read-oriented workflows.
Nodes are not ordinary bucket access-rule principals in the same way users, organizations, and contracts are. For node-to-node replication, verified node membership and the bucket replication policy decide whether a node may receive ciphertext and, for per_bucket_key buckets, matching bucket-key envelope metadata.
Contracts
Smart contracts can act as contract principals after they are deployed and instantiated.
A contract principal is not a normal user and does not sign transactions directly. It is resolved from contract instance consensus state during contract execution and has a contract id, organization id, and owner user id.
For sensitive bucket host calls, two things must line up:
- The contract manifest must declare the bucket access the method requires.
- The bucket must grant matching permissions to the contract principal.
Bucket Owners
The bucket creator user and creator organization have implicit bucket:admin. This implicit admin is part of bucket state.
Because owner admin is implicit, removing an explicit admin rule does not remove admin from the bucket creator user or creator organization.
Explicit Access Rules
Bucket access rules grant permissions to:
userorganizationcontract
Access rules are changed through protocol-versioned transactions:
ADD_BUCKET_ACCESS_RULEUPDATE_BUCKET_ACCESS_RULEREMOVE_BUCKET_ACCESS_RULE
All three require bucket:admin on the target bucket, except for system/genesis operations.
Permission lists are normalized before storage and state hashing. Duplicates are removed, strings are sorted, and unknown permissions are rejected. Empty updates are invalid; remove the rule instead.
Permission Evaluation
NOOSChain evaluates bucket permissions deterministically:
- System actor.
- Implicit bucket owner/admin.
- Direct user or contract access rule.
- Organization access rule.
bucket:admin implies every other bucket permission.
Bucket Permissions
NOOSChain currently defines four bucket permissions.
bucket:read_metadata
Allows the principal to view bucket metadata and record metadata/indexes.
This is required for:
- Reading bucket details.
- Searching records by public indexes.
- Inspecting record metadata.
It does not allow encrypted payload bytes to be returned.
bucket:read_encrypted
Allows the principal to receive encrypted payload bytes when the payload is available and the bucket policy permits it.
This does not decrypt data by itself. The actor still needs matching key material, such as a record key envelope or bucket-key envelope, and the corresponding private key or KMS/HSM capability.
Removing bucket:read_encrypted blocks future authorized API reads for that principal. It does not rewrite historical records or automatically delete ciphertext already stored locally.
bucket:write
Allows the principal to add encrypted records.
ADD_ENCRYPTED_RECORD requires bucket:write. Creator fields must match the signer unless the actor is system. Public index validation and encrypted payload state hashing still apply.
bucket:admin
Allows the principal to administer the bucket.
bucket:admin is required to:
- Add access rules.
- Update access rules.
- Remove access rules.
- Update mutable bucket policy fields.
- Create or rotate bucket keys for
per_bucket_keybuckets.
It implies bucket:read_metadata, bucket:read_encrypted, and bucket:write.
Permissions Do Not Decrypt Data
Bucket permissions decide whether APIs and execution paths may expose metadata, return encrypted bytes, write records, or administer rules.
They do not decrypt payload data. Decryption is explicit and depends on key envelopes, private keys, bucket keys, or future KMS/HSM-backed key operations.
This separation is important:
bucket:read_metadatacan reveal searchable metadata without payload bytes.bucket:read_encryptedcan reveal ciphertext without plaintext.- Key envelopes can make data decryptable only to intended recipients.
- Replication policy can control which nodes retain ciphertext locally.
Create Principals
Principals are created through normal chain transactions.
Create An Organization
Generate a template:
npm run noos -- recipe init:template organization --output org.jsonCreate the organization transaction:
npm run noos -- recipe init:create-organization `
--payload-file org.json `
--signer-public-key="<admin-public-key>" `
--signer-private-key-path admin.key `
--yesRaw transaction form:
npm run noos -- tx build `
--type REGISTER_ORGANIZATION `
--payload-file org.json `
--signer-public-key="<admin-public-key>" `
--signer-private-key-path admin.key `
--output org-tx.json
npm run noos -- tx submit --file org-tx.json --yesCreate A User
Generate a template:
npm run noos -- recipe init:template user --output user.jsonCreate the user transaction:
npm run noos -- recipe init:create-user `
--payload-file user.json `
--signer-public-key="<admin-public-key>" `
--signer-private-key-path admin.key `
--yesRaw transaction form:
npm run noos -- tx build `
--type REGISTER_USER `
--payload-file user.json `
--signer-public-key="<admin-public-key>" `
--signer-private-key-path admin.key `
--output user-tx.json
npm run noos -- tx submit --file user-tx.json --yesCreate A Node
Node registration is part of node membership and governance workflows. The transaction type is REGISTER_NODE, and production node identity also involves node credentials and deployment configuration.
For operator workflows, start with:
Create A Contract Principal
A contract principal exists after a contract is deployed and instantiated. The contract id is then used as principalId with principalType: "contract" in bucket access rules.
For the contract path, see:
Assign Bucket Access With A CLI Recipe
Generate an access-rule payload template:
npm run noos -- recipe init:template bucket-access-rule --output rule.jsonEdit rule.json. Choose:
bucketIdprincipalTypeprincipalIdpermissions
Example permissions:
["bucket:read_metadata", "bucket:read_encrypted", "bucket:write"]Dry-run the assignment:
npm run noos -- recipe init:assign-bucket-principal `
--payload-file rule.json `
--signer-public-key="<bucket-admin-public-key>" `
--signer-private-key-path bucket-admin.key `
--dry-runSubmit it:
npm run noos -- recipe init:assign-bucket-principal `
--payload-file rule.json `
--signer-public-key="<bucket-admin-public-key>" `
--signer-private-key-path bucket-admin.key `
--yesThe signer must have bucket:admin on the target bucket.
Assign Bucket Access With A Raw Transaction
Build the ADD_BUCKET_ACCESS_RULE transaction:
npm run noos -- tx build `
--type ADD_BUCKET_ACCESS_RULE `
--payload-file rule.json `
--signer-public-key="<bucket-admin-public-key>" `
--signer-private-key-path bucket-admin.key `
--output rule-tx.jsonSubmit it:
npm run noos -- tx submit --file rule-tx.json --yesUse UPDATE_BUCKET_ACCESS_RULE to replace an existing rule's permission list. Use REMOVE_BUCKET_ACCESS_RULE to remove an explicit rule.
Inspect Permissions
List explicit bucket access rules:
npm run noos -- observability bucket-access-rulesThe Admin GUI Access Rules page provides the same operator-facing view. These views are read-only; permission changes still go through signed transactions.