paperclip/packages
Dotta da549123cc
feat(db): add inbox archive agent policies (#9654)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The inbox tracks issue visibility separately for each responsible
user
> - Existing inbox archive records only identify the user whose inbox
changed, not the actor that made the change
> - Agent-managed inbox cleanup needs durable agent and heartbeat-run
attribution for auditability
> - Users also need a minimal core policy that can remain open, restrict
access to an allowlist, or disable agent inbox management
> - This pull request adds those database contracts without changing
routes or services
> - The benefit is a company-scoped, auditable foundation for later
agent inbox-management APIs

## Linked Issues or Issue Description

### Subsystem affected

`packages/db` — Drizzle schema and migrations.

### Problem or motivation

Agent workflows such as PR gardening can reduce inbox noise after work
is complete, but existing inbox archive records only identify the user
whose inbox changed. They cannot retain which agent acted or which
heartbeat run performed the action, and there is no user-specific policy
controlling whether agents may manage that inbox.

### Proposed solution

Add database-only contracts for agent-managed inbox archiving: actor
type, agent ID, and heartbeat-run attribution on archive rows, plus one
company-scoped policy per user with `open`, `allowlist`, or `disabled`
mode. Existing archive rows retain `user` attribution by default. Route,
service, and UI behavior are intentionally deferred.

### Alternatives considered

- Store attribution only in activity logs: rejected because archive
state needs durable, directly queryable attribution.
- Add richer per-agent rules immediately: rejected because advanced
policy rules belong in a later or enterprise layer; the core table stays
deliberately minimal.
- Implement APIs in the same change: rejected to keep this
migration-focused PR independently reviewable and safe to deploy.

### Roadmap alignment

`ROADMAP.md` does not currently list this capability. This PR
establishes only the database foundation and does not overlap a listed
roadmap item.

### Additional context

Expected behavior is that legacy archive rows upgrade without backfill,
new archive rows can reference an agent and heartbeat run, and each
company/user pair has at most one agent policy.

## What Changed

- Added actor type, agent ID, and heartbeat run ID attribution columns
to `issue_inbox_archives` with enum checks and `SET NULL` foreign keys.
- Added the company-scoped `user_inbox_agent_policies` table with mode
validation, JSONB agent allowlists, timestamps, and unique company/user
ownership.
- Added migration `0172_inbox_archive_agent_policies.sql` using
idempotent DDL for existing installations.
- Added an embedded PostgreSQL migration test covering legacy rows,
attribution round-trips, policy JSON, and policy uniqueness.

## Verification

- `pnpm --filter @paperclipai/db exec vitest run
src/inbox-archive-agent-policies-migration.test.ts`
- `pnpm --filter @paperclipai/db typecheck`

## Risks

- Low migration risk: adding the non-null actor type uses a constant
`user` default so legacy rows upgrade without a data backfill.
- Agent and run deletions clear attribution foreign keys by design; the
actor type remains available for audit interpretation.
- No API behavior changes are included, so the new contracts remain
unused until follow-up service work lands.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex using GPT-5.4 with reasoning, repository tools, shell
execution, and test execution. The runtime did not expose a
context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-16 08:48:39 -05:00
..
adapter-utils
adapters fix(codex): count raw child output as activity (#9632) 2026-07-15 21:49:30 -05:00
db feat(db): add inbox archive agent policies (#9654) 2026-07-16 08:48:39 -05:00
google-sheets-mcp-server
kv-demo-mcp-server
mcp-server
plugins
shared fix(issues): deduplicate repeated creates (#9650) 2026-07-15 21:45:11 -05:00
skills-catalog
teams-catalog