Files
hub/docs/architecture/storage/roles.md
glm-5.1 2b63cda1c7 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.
2026-05-25 10:56:32 +00:00

5.5 KiB

status, last_updated
status last_updated
draft 2026-04-20

Table Schemas: Roles

Behavioral role definitions. For cross-cutting reference (cascade behavior, index reference, status enums, relations), see table-reference.md. For the full account-role-session model, see ../../agent-roles.md. For the terminology decision, see ADR-012.

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:

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:

[
  { "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:

{
  "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:

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.