Architecture
`dpuAgent` separates confidential metadata, permissions, secret values, and confidential file content so each layer can be controlled independently.
Why The Layers Are Separate
Secrets and confidential objects have different operational needs. Lists and navigation need metadata that can be loaded quickly. Access control list checks need a canonical permission store. Secret values and confidential file content need encrypted persistence and should not leak into metadata files. The agent therefore keeps these concerns in separate storage files instead of collapsing everything into one general-purpose store.
Main Modules
| Module | Role |
|---|---|
lib/dpu-store.mjs |
Main domain surface for secrets, confidential objects, comments, grants, revokes, and access checks. |
lib/dpu-store-internal/storage.mjs |
Storage root resolution, file locking, state load/save, encrypted secret map handling, and confidential blob helpers. |
lib/dpu-store-internal/permissions-manifest.mjs |
Canonical principal identities and access control list (ACL) mutation helpers. |
lib/dpu-store-internal/identity-acl.mjs |
Actor resolution, role checks, and actor-filtered serialization rules. |
tools/dpu_tool.mjs |
Model Context Protocol (MCP) tool dispatch, argument normalization, and auth envelope extraction. |
Storage Layout
The storage root keeps metadata files and encrypted content in separate places:
.dpu-storage/
state.json
permissions.manifest.json
secrets.json
blobs/
.lock/
state.json stores users, secret metadata, and confidential object metadata. permissions.manifest.json stores canonical access control list state. secrets.json stores encrypted secret values. Confidential file bodies are stored as encrypted blobs under blobs/.
What Explorer Delegates
Explorer does not decide who can read a secret value, who can update a confidential object, or how those records are stored. It asks DPU for actor-filtered results and drives the user interface from that response. That keeps the security and storage logic in one place instead of scattering it across plugins and views.