Seal access control
Skill pivyme/suiperpower/core/skills/build/seal-access-control
Integrate Seal threshold encryption and access control on Sui. Use when the user mentions Seal.From its SKILL.md
npx -y skills add pivyme/suiperpower --skill seal-access-controlAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 12 stars12 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
9.0 KB, ~2.2k tokens by cl100k_base, as published. Nobody here has run it
Preamble (run first)
# Suiperpower telemetry. Routes through the CLI so projects.json + Convex stay in sync.
# Silent on failure so the skill never blocks. Opt out: SUIPERPOWER_TELEMETRY=off.
#
# AGENT NOTE: when this skill finishes, run the matching completion command:
# suiperpower track seal-access-control build completed
# Or use "failed" / "aborted" if it ended that way.
command -v suiperpower >/dev/null 2>&1 && suiperpower track seal-access-control build started >/dev/null 2>&1 &
true
If TEL_PROMPTED is no, before doing real work, ask the user:
Help suiperpower get better. We track which skills get used and how long they take. No code, no file paths, no PII. Change anytime in
~/.suiperpower/config.json.A) Sure, anonymous B) No thanks
Write the answer to ~/.suiperpower/config.json telemetryTier field and create ~/.suiperpower/.telemetry-prompted. Then continue.
What this skill does
Integrates Seal into a Sui project so the user can encrypt data client-side and control decryption through Move access policies on chain. Picks the right access pattern (allowlist, subscription, token-gate, time-lock, etc.), writes the Move policy module with seal_approve functions, wires up the @mysten/seal TS SDK for encrypt and decrypt, and verifies a real round-trip before declaring done.
When to use it
- The project needs access-controlled encryption tied to on-chain state (NFT gate, allowlist, subscription, DAO vote).
- The user wants to encrypt Walrus blobs so only authorized users can decrypt.
- The user needs time-locked encryption (content becomes public after a deadline).
- The user is building gated content, encrypted NFTs, secret ballots, or private user data.
When NOT to use it
- If the user has not picked a project yet, use
find-next-sui-ideafirst. - If the user has not scaffolded a project, use
scaffold-projectfirst. - If the user only needs Walrus storage without encryption, use
walrus-storageinstead. - If the user wants simple single-user AES encryption with a user-held key, that does not need Seal. Point them to standard AES-GCM and skip this skill.
- If the user wants to write raw Move without encryption, use
build-with-move.
If you activated this and the user actually wants something else, consult skills/SKILL_ROUTER.md and hand off.
Inputs
- A Sui project (Move package and/or TS frontend).
- Optional:
.suiperpower/build-context.mdfromscaffold-project. Read it if present. - The access control requirement: who should be able to decrypt and under what conditions.
If unclear, interview the user for:
- What data is being encrypted? (blobs, messages, documents, NFT content)
- Who should be able to decrypt? (specific addresses, NFT holders, paid subscribers, anyone after a date)
- Will encrypted data live on Walrus or elsewhere?
- Is there an existing Move package to extend, or start fresh?
Outputs
-
A Move module with one or more
seal_approveentry functions implementing the access policy. -
TS integration code using
@mysten/sealfor encrypt and decrypt flows. -
A working SessionKey flow with personal message signing.
-
Optional: Walrus integration for storing encrypted blobs (uses
walrus-storagepatterns). -
Append to
.suiperpower/build-context.md:## seal-access-control session, <timestamp> - pattern: <whitelist | subscription | account_based | private_data | tle | voting | key_request> - policy module: <module::name> - seal_approve functions: <names> - package id (testnet): <id or pending> - walrus integration: <yes | no> - open issues: <list>
Workflow
-
Context gathering
- Read
.suiperpower/build-context.mdif it exists. - Confirm the user's access control requirement and who should decrypt.
- Check if the project already has Move modules or a TS frontend.
- Read
-
Pick the access pattern
- Use the decision table below. Confirm the choice with the user before writing code.
- If none of the standard patterns fit, compose from multiple or write a custom
seal_approvefunction.
-
Write the Move policy module
- Implement
seal_approveentry functions following the Seal convention (seereferences/seal-patterns.md). - Every
seal_approvefunction: name starts withseal_approve, first param isid: vector<u8>, must not modify state. - Add admin functions if the pattern requires setup (e.g., allowlist add/remove, subscription creation).
- Write at least one Move test that verifies the policy grants and denies correctly.
- Implement
-
Integrate the TS SDK
- Install
@mysten/sealand@mysten/sui. - Initialize
SealClientwith testnet key server config (seereferences/seal-quickstart.md). - Wire the encrypt flow: build identity from policy object + nonce, call
client.encrypt(). - Wire the decrypt flow: create
SessionKey, get personal message signature from wallet, buildseal_approvePTB, callclient.decrypt().
- Install
-
Walrus integration (if applicable)
- Encrypt data via Seal, upload ciphertext to Walrus, store
blobIdon chain. - On retrieval: fetch ciphertext from Walrus, decrypt via Seal after policy check.
- See
walrus-storageskill andreferences/seal-quickstart.mdfor the canonical pattern.
- Encrypt data via Seal, upload ciphertext to Walrus, store
-
Test the round-trip
- Encrypt real data, store it (Walrus or local), decrypt with an authorized identity.
- Verify the decrypted bytes match the original plaintext.
- Test denial: attempt decryption with an unauthorized identity and confirm it fails.
-
Writeback
- Append session details to
.suiperpower/build-context.md.
- Append session details to
-
Closing handoff
- If
.suiperpower/intent.mdexists and the session was non-trivial (new module, new sponsor integration, or material changes to public functions), recommendverify-against-intentas the next step so drift is caught before shipping. - If no
intent.mdexists and the session was non-trivial, surface that gap once: offerclarify-intentto backfill, do not force it.
- If
Decision table: which pattern to pick
| Use case | Pattern | Module |
|---|---|---|
| Admin controls who can decrypt | whitelist | Admin-managed address allowlist |
| Paid, time-limited access | subscription | Fee + TTL, auto-expires |
| Encrypt to a specific address | account_based | Only that address decrypts |
| Creator-only private data | private_data | Only the object creator decrypts |
| Content unlocks after a date | tle (time-lock) | Anyone decrypts after timestamp |
| Secret ballot / sealed-bid auction | voting | Threshold decryption after vote closes |
| Delegated access via witness | key_request | Third party grants access on behalf |
If the user's requirement spans two patterns (e.g., allowlist that expires), compose them in a single module. The seal_approve convention is flexible enough for custom logic.
Quality gate (anti-slop)
Before reporting done, the skill asks itself the following and refuses to declare success if any answer is no:
- Does the Move policy module compile with
sui move build? - Does every
seal_approvefunction follow the convention (name prefix,id: vector<u8>first param, no state mutation)? - Did the round-trip test actually encrypt, store, retrieve, and decrypt real data?
- Was denial tested (unauthorized identity fails to decrypt)?
- Is
verifyKeyServersdocumented asfalsefor dev andtruefor production? - If Walrus is involved, does the ciphertext actually live on Walrus, not just in local memory?
- Is SessionKey TTL explicitly set, not silently defaulted?
If any answer is no, the skill reports the gap and works through it before claiming the integration is complete.
References
On-demand references (load when relevant to the user's question):
references/seal-quickstart.md: SealClient init, encrypt, decrypt, SessionKey, Walrus integration recipes.references/seal-patterns.md: All 7 Move access patterns withseal_approvefunction signatures and when to use each.references/seal-pitfalls.md: Common mistakes with Seal integration and how to avoid them.
Knowledge docs (load when scope expands beyond what is in references):
skills/data/sui-knowledge/sponsor-docs/walrus.md: Walrus concepts and integration for encrypted blob storage.
External docs (fetch at runtime for the latest API surface):
- Seal SDK: https://sdk.mystenlabs.com/seal
- Seal repo and examples: https://github.com/MystenLabs/seal
- Seal blog post: https://blog.sui.io/seal-programmable-access-control/
Use in your agent
- Claude Code:
claude "/suiper:seal-access-control <your message>" - Codex:
codex "/seal-access-control <your message>" - Grok Build: run
grok, then/seal-access-control <your message>in the session - Cursor: paste a chat message that includes a phrase like "encrypt with Seal" or "gated content", or load
~/.cursor/rules/seal-access-control.mdcand reference it.
If you activated this and the user actually wants something else, consult skills/SKILL_ROUTER.md and hand off.
What ships with it: 4 files
15.6 KB alongside SKILL.md
agents/
- openai.yaml367 B
references/
- seal-patterns.md7.3 KB
- seal-pitfalls.md3.6 KB
- seal-quickstart.md4.3 KB