Bind a skill with grants
When a skill's manifest declares permissions or required secrets, binding it does not activate it. The binding row is created with pending_grants = true and the resolver filters it out. An admin with scaiskills:grant has to satisfy each declared item before the binding participates in any turn.
This walks through the full flow against the pricing-policy skill from Publish a skill, which declares one permission (scaidrive:read:/policies/) and one required secret (stripe_read_only).
1. Create the binding#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
The secret mapping was supplied at bind time, so the secrets axis is satisfied. The permission axis isn't — pending_grants is true and the binding is invisible to resolve.
2. Inspect the gap#
List the bindings for the scope to see what's pending:
1 2 | |
The response shows the binding with pending_grants: true. The original manifest's permissions list is the source of truth — look it up via the skill detail endpoint, or read it off your local copy of the bundle.
3. Grant the permission#
An admin with scaiskills:grant runs:
1 2 3 4 5 6 | |
1 2 3 4 5 | |
1 2 3 4 5 | |
Behind the scenes the grant row goes into mod_scaiskills_permission_grants, the binding's manifest is rechecked, and if every declared permission has a grant and every required secret has a mapping, pending_grants flips to false. The Redis cache for the scope is invalidated.
For skills with multiple declared permissions, call grant once per permission string. The grants are independent rows — revoking later means deleting one without affecting the others.
4. Confirm via resolve#
1 2 3 4 | |
The pricing-policy slug should now appear in the skills array.
What happens when the skill bumps a version#
If the binding was created with a floating ref (^0.1), and a new 0.2.0 is published that declares a new permission the existing binding hasn't been granted, the next resolve sees the version roll forward, the manifest's permission list no longer matches the grants, and pending_grants flips back to true. The binding falls out of results until an admin grants the new permission.
Pinned bindings (0.1.0) are immune — the lockfile and the resolved manifest are frozen.
What happens when a required secret is missing#
There is no per-secret grant endpoint. Required secrets are supplied at bind time via secret_mappings. If you missed one, the binding stays in pending_grants and the only correction is to delete it and create a fresh one with the complete mapping. The grant flow is for permissions only.
What happens at runtime#
ScaiSkills does not enforce the granted permissions itself. It only enforces that the bind-time approval gate was cleared. The actual permission check happens in whatever module the permission targets — ScaiDrive enforces scaidrive:read:/policies/, the network egress policy enforces network:*, and so on. ScaiSkills' role is the approval ledger, not the policy engine.
Done#
The binding is active, the grants are auditable, and the supply-chain gate is in place for future version rolls. Iterate on the skill's body and references without touching the binding; touch the binding only to change scopes, change the version ref, or revoke.