What Is OpenWork Den? Understanding the Organization Control Plane for Teams, Skills, and Plugins
OpenWork Den is the control-plane backend that governs every organization-wide operation in OpenWork, running as a Hono-based HTTP service with a companion web UI to centrally manage authentication, teams, policies, and plugin marketplace access.
OpenWork Den serves as the single source of truth for enterprise deployment of the OpenWork platform. Built as a modular stack comprising the Den API and Den Web console, it coordinates how organizations provision users, distribute AI skills, and enforce security policies across desktop clients and agent runtimes. This article examines how Den implements organization control plane functionality—from team hierarchy management to plugin access grants—based on the source code in the different-ai/openwork repository.
How OpenWork Den Architecture Implements the Control Plane
The Den stack separates concerns across two main deliverables: a lightweight API layer and an administrative web interface.
| Component | Implementation | Responsibility |
|---|---|---|
| Den API | Hono HTTP framework (ee/apps/den-api/) |
REST endpoints for auth, org management, policies, and marketplace |
| Den Web | Companion admin UI (ee/apps/den-web/) |
Browser-based console for bulk operations and visualization |
| den-db | Drizzle ORM + MySQL (ee/packages/den-db/) |
Persistence layer for org, team, and plugin schemas |
This architecture lets operators run Den as a centralized service while agents and desktop clients consume it via standard HTTP calls.
Authentication and Session Management in Den
Den delegates authentication to Better Auth, wrapping its routes under /api/auth/* as documented in the Den API README.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Desktop App │────▶│ Den API │────▶│ Better Auth │
│ or Agent │ │ /api/auth/* │ │ (OAuth, │
│ │◀────│ (wraps) │◀────│ SAML, etc) │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
Signed session cookie
(used for subsequent calls)
The middleware layer validates this session on every protected endpoint, extracting the caller's organization context before allowing operations to proceed.
Organization and Team Management
Den stores organizational hierarchy in MySQL tables defined in [ee/packages/den-db/src/schema/teams.ts](https://github.com/different-ai/openwork/blob/main/ee/packages/den-db/src/schema/teams.ts).
The schema enforces three key constraints:
teamtable: Unique names scoped to each organization (org_id+namecomposite unique key)team_membertable: Many-to-many linking users to teams with role annotations- Organization isolation: Every query filters by
org_idto prevent cross-tenant data leakage
# Seed a demo organization with teams and members
pnpm --filter @openwork-ee/den-api seed:demo-org
This command creates "Acme Robotics" with sample users, teams, and membership links, demonstrating how Den structures multi-team enterprises.
Policy Enforcement and Access Control
The organization control plane applies governance through dedicated policy tables:
| Policy Type | Storage Location | Enforcement Point |
|---|---|---|
| Desktop policies | desktop_policy table |
Client configuration fetch |
| SSO providers | sso_provider table |
Authentication routing |
| SCIM provisioning | SCIM-related tables | User lifecycle management |
Middleware documented in the Den API README validates the caller's scope—org, team, or individual user—before permitting mutations.
Policy definitions themselves live in [packages/types/src/den/desktop-policies.ts](https://github.com/different-ai/openwork/blob/main/packages/types/src/den/desktop-policies.ts), where TypeScript interfaces specify which model providers, update channels, and feature flags an organization permits.
# Query desktop policy for an organization
curl "http://localhost:8790/v1/policies/desktop?orgId=org_abcdef1234567890" | jq .
The Marketplace Model: Managing Skills and Plugins
Den implements plugin distribution through a Marketplace abstraction with granular access grants. The core schema in [ee/packages/den-db/src/schema/sharables/plugin-arch.ts](https://github.com/different-ai/openwork/blob/main/ee/packages/den-db/src/schema/sharables/plugin-arch.ts) defines:
plugintable: Registered skills and extensions with metadataplugin_access_granttable: Permission links scoped to org, team, or individual member
Grant scoping follows a hierarchy: organization-wide grants apply to all teams and members, while team-specific or user-specific grants override with finer precision.
Publishing and Assigning Plugins
Administrators interact with plugins through REST endpoints:
# List all plugins available to the authenticated organization
curl -H "Cookie: <session-cookie>" \
http://localhost:8790/v1/marketplace/plugins | jq .
Granting access requires a POST to the plugin access grants endpoint:
curl -X POST http://localhost:8790/v1/marketplace/plugin-access-grants \
-H "Content-Type: application/json" \
-d '{
"pluginId": "plg_abcdef1234567890",
"teamId": "team_1234567890abcdef",
"role": "editor"
}' | jq .
The role field supports permission levels (viewer, editor, admin) that downstream clients enforce when executing plugin functionality.
The Client Control Plane Flow
Every OpenWork desktop session or agent initialization follows a five-step enrollment against Den:
- Authenticate — Exchange credentials for signed session via Better Auth
- Resolve organization —
GET /v1/me/orgreturns active org context - Load policy bundle — Desktop policies, allowed models, and constraints
- Fetch marketplace catalog — Filtered to granted plugins for this user/team/org
- Enforce access — Middleware validates grants on every subsequent API call
This flow ensures continuous central governance: clients cache policies and catalogs locally but must revalidate with Den for mutations or periodic refresh.
Observability and Security Hardening
Den includes production-hardened observability:
- OTEL/Sentry integration — Request tracing and error aggregation (configurable backends)
- Credential redaction — Sensitive fields filtered from logs before persistence
- SSRF protection — Network-level guards against server-side request forgery
Configuration details appear in the Den API README observability section.
Running OpenWork Den Locally
The standard development workflow brings up all components:
# Terminal 1: Start the Den API on :8790
pnpm --filter @openwork-ee/den-api dev:local
# Terminal 2: Start the admin web UI on :3005
pnpm --filter @openwork-ee/den-web dev:local
These commands launch the full control plane stack for local testing and plugin development.
Summary
- OpenWork Den is the Hono-based control plane that centralizes organization management for the OpenWork platform
- Team hierarchy enforces org-scoped isolation via MySQL schemas in
teams.ts - Plugin marketplace uses granular access grants (
plugin_access_grant) to distribute skills across org, team, or user scopes - Policy enforcement combines middleware validation with typed policy definitions for desktop clients
- Better Auth integration provides pluggable authentication while Den manages authorization and session state
Frequently Asked Questions
How does Den prevent unauthorized cross-organization access?
Den middleware validates the session's org_id claim against the requested resource on every operation. Database queries include mandatory org_id filters, and unique constraints prevent name collisions between organizations rather than allowing data leakage.
What authentication methods does OpenWork Den support?
Den wraps Better Auth, which supports OAuth 2.0, OpenID Connect, SAML, and password-based flows. Additional SSO providers integrate through the sso_provider table and associated configuration, as noted in the Den API middleware documentation.
Can plugins be restricted to specific teams within an organization?
Yes. The plugin_access_grant table accepts org_id, team_id, or member_id scope fields, allowing administrators to publish organization-wide defaults while restricting sensitive plugins to specific teams or individual power users.
How do desktop clients receive policy updates from Den?
Clients fetch the active policy bundle during initialization via GET /v1/policies/desktop and cache it locally. Den can signal policy changes through session refresh or version-stamped configurations, with the client re-querying on context switches or periodic refresh intervals.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →