Setup repo: migrate architecture specs, code stubs, and tasks from alkhub_ts
Copy architecture docs, ADRs, storage domain specs, research, reviews, and 56 storage architecture tasks from the alkhub_ts monorepo. Adapt for standalone @alkdev/hub repo structure (src/ not packages/hub/). Sanitize all sensitive information: - Replace private IPs (10.0.0.1) with localhost defaults - Remove internal server hostnames (dev1, ns528096) - Replace /workspace/ private paths with npm package references - Remove hardcoded credentials from examples - Rewrite infrastructure.md without private network details Add Deno project scaffolding: deno.json (pinned deps), .gitignore, AGENTS.md, entry point. Migrate existing code stubs (crypto, config types, logger) with updated import paths.
This commit is contained in:
105
docs/architecture/storage/roles.md
Normal file
105
docs/architecture/storage/roles.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
status: draft
|
||||
last_updated: 2026-04-20
|
||||
---
|
||||
|
||||
# Table Schemas: Roles
|
||||
|
||||
Behavioral role definitions. For cross-cutting reference (cascade behavior, index reference, status enums, relations), see [table-reference.md](./table-reference.md). For the full account-role-session model, see [../../agent-roles.md](../../agent-roles.md). For the terminology decision, see [ADR-012](../../../decisions/ADR-012-agent-vs-role-vs-account.md).
|
||||
|
||||
### `roles`
|
||||
|
||||
Behavioral role definitions that any account can fill during a session. Roles define what operations are available, what permissions are granted, and what scope constraints apply. Currently defined in `.opencode/agents/*.md` files; this table enables database storage and runtime permission resolution.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| commonCols | — | id, metadata, createdAt, updatedAt |
|
||||
| name | text NOT NULL UNIQUE | Role identifier (e.g., "architect", "implementation-specialist") |
|
||||
| description | text | Human-readable description |
|
||||
| mode | text NOT NULL | `primary` (user-facing) or `subagent` (spawned by coordinator) |
|
||||
| temperature | real | Model sampling temperature (default: 0.2 for subagents, 0.3 for primary) |
|
||||
| permissions | jsonb NOT NULL DEFAULT `[]` | Permission ruleset — array of `{ action, permission, pattern }` rules, evaluated first-match |
|
||||
| tools | jsonb NOT NULL DEFAULT `{}` | Tool availability map — `{ toolName: boolean }` for enabled/disabled tools |
|
||||
| prompt | text | System prompt template |
|
||||
| parentId | text | FK → roles.id — Parent role for inheritance. onDelete: SET NULL — deleting a parent detaches children. |
|
||||
| scopes | jsonb NOT NULL DEFAULT `[]` | API key scopes this role requires (string array, used during permission resolution) |
|
||||
| data | jsonb | Additional role-specific configuration (model selection, max steps, etc.) |
|
||||
|
||||
**Indexes**: `unq_roles_name` UNIQUE on `(name)`, `idx_roles_parent_id` on `(parentId)`, `idx_roles_mode` on `(mode)`.
|
||||
|
||||
**`permissions` shape**: A `Permission.Ruleset` — an ordered array of rules evaluated first-match:
|
||||
|
||||
```ts
|
||||
type PermissionRule = {
|
||||
action: "allow" | "deny" | "ask"; // What to do when this rule matches
|
||||
permission: string; // e.g., "edit", "read", "bash", "webSearch"
|
||||
pattern: string; // Glob pattern for path-based matching (e.g., "src/**", "*")
|
||||
};
|
||||
type PermissionRuleset = PermissionRule[];
|
||||
```
|
||||
|
||||
Example for implementation-specialist:
|
||||
```json
|
||||
[
|
||||
{ "action": "allow", "permission": "read", "pattern": "**" },
|
||||
{ "action": "allow", "permission": "write", "pattern": "src/**" },
|
||||
{ "action": "allow", "permission": "edit", "pattern": "src/**" },
|
||||
{ "action": "allow", "permission": "bash", "pattern": "deno *" },
|
||||
{ "action": "deny", "permission": "bash", "pattern": "*" },
|
||||
{ "action": "allow", "permission": "webSearch", "pattern": "*" }
|
||||
]
|
||||
```
|
||||
|
||||
**`tools` shape**: A simple boolean map for which tools are available to this role:
|
||||
|
||||
```json
|
||||
{
|
||||
"read": true,
|
||||
"write": true,
|
||||
"edit": true,
|
||||
"glob": true,
|
||||
"grep": true,
|
||||
"bash": true,
|
||||
"webSearch": true,
|
||||
"webfetch": true
|
||||
}
|
||||
```
|
||||
|
||||
**Role inheritance**: When a role has a `parentId`, the child role inherits `permissions` and `tools` from the parent, with the child's values taking priority. Specifically:
|
||||
- `permissions`: The parent's ruleset is prepended before the child's ruleset. First match wins, so child rules override parent rules for the same pattern.
|
||||
- `tools`: Union of parent and child tool sets. If both define a tool, the child's value takes priority.
|
||||
- `temperature`, `prompt`, `model`, `scopes`: Child values override parent values entirely (no merging).
|
||||
- Max inheritance depth: 3 levels. Circular inheritance is prevented at role creation time.
|
||||
|
||||
**`data` shape**: Additional configuration that varies by role:
|
||||
|
||||
```ts
|
||||
type RoleData = {
|
||||
model?: { // Override model selection
|
||||
providerID: string; // e.g., "anthropic", "openai"
|
||||
modelID: string; // e.g., "claude-opus-4-5-20250101"
|
||||
};
|
||||
steps?: number; // Max agentic steps per turn
|
||||
topP?: number; // Top-P sampling parameter
|
||||
color?: string; // Display color for UI
|
||||
hidden?: boolean; // Don't show in role selection UI
|
||||
source?: "builtin" | "file" | "database"; // Where this role definition came from
|
||||
filePath?: string; // Source file path (for file-based roles)
|
||||
};
|
||||
```
|
||||
|
||||
**OpenCode compatibility**: When importing from `.opencode/agents/*.md`, the YAML frontmatter maps to:
|
||||
- `description` → from frontmatter `description`
|
||||
- `mode` → from frontmatter `mode`
|
||||
- `temperature` → from frontmatter `temperature`
|
||||
- `tools` → from frontmatter `tools`
|
||||
- `permissions` → converted from frontmatter `permission` (OpenCode uses `Permission.Ruleset` format)
|
||||
- `prompt` → from markdown body content
|
||||
- `data.model` → from frontmatter `model`
|
||||
- `data.steps` → from frontmatter `steps`
|
||||
- `data.source` → `"file"`
|
||||
- `data.filePath` → path relative to project root
|
||||
|
||||
**Migration path**: Phase 1 uses `.opencode/agents/*.md` files. Phase 2 adds a `roles.sync` operation that reads files and upserts into this table. Phase 3 makes the database authoritative with files as a version-controlled editing surface.
|
||||
|
||||
**Sessions reference**: `sessions.roleName` is a free-form string that references `roles.name` by convention, but there is no FK constraint. Sessions may use role names not yet in the `roles` table (e.g., file-based roles not yet synced). A FK constraint may be added in Phase 3 when the database becomes authoritative.
|
||||
Reference in New Issue
Block a user