traverse-framework / traverse-framework/registry

Publish capability: core.check-declared-permission (authz from declared roles/permissions)

Open
#496 0 comments 0 reactions 0 assignees View on GitHub
enhancement good first issue help wanted no-spec-needed
Dominant language
Rust
Stars
1
Forks
1
Avg merge
1h 17m
Merged PRs (30d)
217

Description

## Why

`core.authorize` is a full policy evaluator (RBAC/hybrid rules, tenants, break-glass, obligations). Many agent tool gates only need a **thin check**: does this principal's *declared* roles/permissions satisfy a required permission for an action? That smaller contract is easier for first publishers and for runtime wrappers that already resolved roles upstream.

## One-PR ask

Publish **`core.check-declared-permission@1.0.0`**:

**Inputs:**
- `principal`: `{ "id": string, "roles"?: string[], "permissions"?: string[] }`
- `required`: `{ "permission": string }` OR `{ "any_of": string[], "all_of"?: string[] }` — pick a tight shape; document
- `role_permissions?`: map of role → permission string[] (caller-supplied so evaluation stays pure)
- `action?`: string (echo/trace only)
- `resource?`: `{ "type"?: string, "id"?: string }` (echo/trace only; **no** resource-attribute policy language — that's `core.authorize`)

**Outputs:**
- `decision`: `allow` | `deny`
- `reason_code`: e.g. `permission_granted` | `role_grants_permission` | `missing_permission` | `invalid_principal`
- `matched`: string[] (which permissions/roles satisfied)
- `evaluation_trace`: string[]

**Behavior:** Deterministic set logic. Deny by default. Invalid input → deny + `invalid_*` reason (fail closed). Prefer requiring `role_permissions` when roles are used so the capability never hardcodes a role catalog.

Follow [`CONTRIBUTING.md`](https://github.com/traverse-framework/registry/blob/main/CONTRIBUTING.md) and [`capabilities/README.md`](https://github.com/traverse-framework/registry/blob/main/capabilities/README.md) publish checklist.

- Include `capability-src/` with real Rust tests meeting registry coverage gates (`functions` 100%, lines/regions ≥ 95%)
- Use `traverse-cli capability publish` (or the documented scaffold) so `artifact.digest` / `artifact.url` survive
- Declare `authoring.method` (`human` or `llm-assisted`)
- Ensure every `use_cases[].persona_ref` resolves (scaffold personas if needed)
- Run `bash scripts/ci/pre_pr_check.sh ` before opening
- One capability per PR; branch from `origin/main`, not another `publish/*` branch

**Apps are not ready — publish the capability only.** No app wiring, no demo product surface.

## Out of scope

- Replacing `core.authorize` (no break-glass, no obligations, no tenant isolation rules)
- OIDC/JWT parsing or network calls to an IdP
- Mutating sessions (`identity.*` caps)

## Done when

- CI green; published in next index
- Tests: direct permission allow, role-mapped allow, deny default, invalid principal
- Contract text explicitly distinguishes from `core.authorize`

## Host / deps notes

**Pure WASM.** No connector, no host state, no network. Caller supplies already-declared roles/permissions.

## Labels

`help wanted` · `good first issue` · `enhancement` · `no-spec-needed`

Contributor guide

Open the contributing guide

Research direction

Start with CONTRIBUTING.md and capabilities/README.md, then inspect the documented scaffold or traverse-cli capability publish flow and the capability-src Rust test requirements. Run bash scripts/ci/pre_pr_check.sh against the draft PR body. Done means a pure WASM capability is published with resolved persona references, preserved artifact metadata, passing tests for permission, role, deny, and invalid-principal cases, and contract text distinguishing it from core.authorize.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
authorization, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.