Skip to content

Data Buckets

NOOSChain stores application and project data in data buckets. In the rest of the documentation, and in most command names, we call them buckets.

A bucket is a permissioned container for encrypted records. It defines who owns the data, how record metadata is indexed, how encrypted payloads are handled, and which actors may read, write, administer, or receive encrypted bytes.

Buckets are consensus state. That means bucket creation, policy updates, access rules, and encrypted-record metadata are committed through signed transactions and replayed deterministically by every node.

What A Bucket Contains

A bucket has:

  • A stable bucket id.
  • A human-readable name and optional description.
  • Creator user and creator organization ids.
  • A replication policy.
  • An encryption mode.
  • Optional metadata.
  • Optional public index schema for records.
  • Access rules granting bucket permissions to users, organizations, or contracts.

The bucket row itself does not contain plaintext payload data. Encrypted record payload bytes are availability-layer data. The chain records deterministic metadata such as payload hashes, encryption metadata, key-envelope references, public indexes, creator identity, and transaction hash.

Ownership

The user and organization that create a bucket have implicit bucket:admin. This implicit ownership is stored in bucket state, so replay can derive it without an explicit access-rule row.

Other users, organizations, or contracts receive access through bucket access rules. See Permission Model for the full model.

Encryption Modes

NOOSChain supports two bucket encryption modes.

per_record_key

In per_record_key mode, every encrypted record uses a fresh random data encryption key, or DEK.

The record stores encrypted key envelopes for that record DEK. A holder of the matching private key can unwrap the record DEK and decrypt the payload. This is the more isolated model: each record has its own key material.

Use this when record-level key separation matters more than simpler key rotation.

per_bucket_key

In per_bucket_key mode, the bucket has an active bucket DEK. Records are encrypted with the active bucket key and store a bucketKeyId and bucketKeyVersion.

Record-level key envelopes are normally empty in this mode. A decryptor first unwraps the bucket-key envelope, then uses the bucket DEK to decrypt records written under that key version.

Bucket keys are consensus state:

  • CREATE_BUCKET_KEY creates version 1 for a per_bucket_key bucket.
  • ROTATE_BUCKET_KEY creates the next version and marks the previous active key as rotated.
  • Existing records stay pinned to the key version used when they were created.
  • Current rotation is forward-only; it does not re-encrypt historical records.

Plaintext DEKs are never persisted. Development helpers may accept raw bucket DEK material for local MVP/testing flows, but production deployments should use client-side encryption or KMS/HSM-backed key operations.

Replication Policy

A bucket replication policy controls how encrypted payload bytes are materialized during sync and backfill. It does not change the payload hash or rewrite historical records.

metadata_only

Nodes sync record and bucket metadata, but future synced records omit encrypted payload bytes. Backfill skips ciphertext retrieval.

Use this when a node should know that records exist but should not retain their encrypted payload bytes.

replicate_encrypted_to_authorized_nodes

Future synced records include ciphertext only for nodes whose organization currently has bucket:read_encrypted or bucket:admin.

Use this when encrypted payload custody should follow bucket permissions and verified node membership.

replicate_encrypted_to_all_nodes

Future synced records include ciphertext for all syncing nodes.

Use this only when all syncing nodes are expected to retain encrypted payload bytes. Bucket permissions still control application/API access to metadata and ciphertext.

Public Index Schemas

Buckets may define an index schema for public record indexes. These indexes are not encrypted payload data. They exist so applications can search record metadata without decrypting every payload.

Record search can filter on public metadata with query parameters such as:

text
index.status=approved
index.projectId=project-a

Those filters are validated against the bucket index schema and executed through typed record-index rows. Public indexes should only contain values that are safe to expose as searchable metadata.

What Can Change Later

UPDATE_BUCKET_POLICY can update:

  • replicationPolicy
  • metadata

At least one mutable field must be present.

Changing encryptionMode is intentionally not supported in the current MVP. If an update payload includes encryptionMode, execution fails deterministically. This avoids ambiguous historical key and record semantics for buckets that already contain encrypted records.

Policy changes affect future sync, backfill, and metadata behavior. They do not rewrite historical blocks, records, state roots, payload hashes, or already stored local ciphertext.

Create A Bucket With A CLI Recipe

The guided recipe path is the easiest way to create a bucket.

First, generate a bucket payload template:

powershell
npm run noos -- recipe init:template bucket --output bucket.json

Edit bucket.json. Set the bucket id, name, creator user and organization, replication policy, encryption mode, metadata, and optional index schema.

Then dry-run the transaction:

powershell
npm run noos -- recipe init:create-bucket `
  --payload-file bucket.json `
  --signer-public-key="<creator-public-key>" `
  --signer-private-key-path creator.key `
  --dry-run

Submit it when the payload and signer are correct:

powershell
npm run noos -- recipe init:create-bucket `
  --payload-file bucket.json `
  --signer-public-key="<creator-public-key>" `
  --signer-private-key-path creator.key `
  --yes

The signer must be the creator user, unless the transaction is a system/genesis operation. The creator user must belong to the creator organization.

Create A Bucket With A Raw Transaction

You can also build and submit the CREATE_BUCKET transaction directly:

powershell
npm run noos -- tx build `
  --type CREATE_BUCKET `
  --payload-file bucket.json `
  --signer-public-key="<creator-public-key>" `
  --signer-private-key-path creator.key `
  --output bucket-tx.json

Submit the signed transaction:

powershell
npm run noos -- tx submit --file bucket-tx.json --yes

Use the recipe path first unless you specifically need the lower-level transaction workflow.

Inspect Buckets

Operators can inspect bucket state through observability:

powershell
npm run noos -- observability buckets

Access rules are inspected separately:

powershell
npm run noos -- observability bucket-access-rules

The Admin GUI also has bucket and access-rule views for operator workflows.

Audience-first NOOSChain documentation.