mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-22 16:51:28 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Agents can submit suggestions and complaints while they work. > - Operators currently need database access to read those messages. > - That makes it hard to find feedback from one agent or share a specific message. > - This pull request adds a standard Commentary tab in Audit. > - Operators can filter messages, browse 50 at a time, and share links to full message dialogs. ## Linked Issues or Issue Description Refs #15367, which added feedback storage and agent submission. The duplicate search found no open PR for a commentary reader. **Subsystem affected** Server, shared API contracts, and the board UI. **Problem or motivation** Agent suggestions and complaints are stored but have no board reader. Operators must query the database to inspect feedback. **Proposed solution** Add Commentary to Audit without an experimental toggle. Show previews, agent and message-type filters, text search, and 50-message pages. Opening a row updates the URL. A copied URL opens the full message with its agent, task, and run context. **Alternatives considered** Direct database queries remain useful for operators, but do not provide a normal product workflow. An experimental setting would add setup to a read-only audit page. **Roadmap alignment** This completes the operator view for the existing feedback feature. It supports human oversight and does not change agent execution or task ownership. ## What Changed - Add company-scoped, board-only list and detail endpoints with audit permission and source-task privacy checks. - Return bounded previews and counts. Fetch full bodies only when a message opens. - Add the Commentary tab, search, filters, 50-row pagination, and URL-based selection. Audit tab destinations work in both layouts, with a classic sidebar entry for Commentary. - Add production Storybook examples for populated, filtered, linked, long, paginated, empty, loading, failed, denied, mobile, and light states. - Update API documentation and the feature and agent access maps. ## Verification - Final head `abc4a251c14cfbfec007542214beec528f2b18bf`: 55 checks pass; two conditional Storybook checks are skipped. The PR workflow is successful. Greptile is 5/5 with all findings resolved. - Focused database, HTTP, submission, OpenAPI, and UI regression tests cover company isolation, task privacy, filter bounds, 50-row pagination, and copied message links. - Browser Storybook journeys cover row opening, direct links, combined filters, search, and pagination. Storybook uses synthetic API fixtures; database authorization is tested separately. - Token gates, feature maps, and Storybook catalog validation pass. - `pnpm -r typecheck`, `pnpm build`, and `pnpm build-storybook` pass on the rebased branch. All 80 focused tests and all 37 Audit tests pass, including the real App route table in both layouts, task grant/revocation through HTTP, deleted-task privacy, and URL UI regressions. The full suite passes in the parallel PR CI matrix. The local serial full-suite run was stopped before completion after checking the recorded 94-minute serial duration. Local focused tests, workspace typecheck, production build, and final server/UI checks pass. - The linked-message Storybook test initially asserted against the loading dialog. It now waits for the message body; both direct-link and row-open journeys pass. - Native and legacy deleted-task privacy regressions failed before the fix and pass afterward. The reader checks the run task binding after the task foreign key clears. - A rapid search-then-agent-filter browser regression reproduced the search overwriting the selected agent. The pending search now restarts when URL filters change. The same browser test passes with both filters applied. - CI found two existing AuditHub assertions that still expected five tabs. They now assert the six-tab model and selected-company Commentary rendering. All 37 Audit tests pass. All other test and build jobs passed before this test-only correction. - The [agent-chat attachment browser test](https://github.com/paperclipai/paperclip/actions/runs/39307881171/job/118250189664) timed out waiting for an attachment preview. The [same shard passed on the prior head](https://github.com/paperclipai/paperclip/actions/runs/39306658703/job/118245498343) with identical application code; the intervening change only updates AuditHub unit tests. The single retry passed on the same head. The precise cause of the earlier failure remains unconfirmed. ## Risks - Commentary may contain sensitive task context. The reader requires board access and audit permission, and filters source-task visibility before returning previews, counts, or full bodies. - Text search scans stored message bodies. Pages are bounded and full bodies are fetched on demand. - Offset pagination can shift if new messages arrive while paging. Ordering uses timestamp and ID for stable ties. - No database migration or agent submission behavior changes are required. ## Model Used - OpenAI Codex, GPT-6 family, with reasoning, tool use, browser interaction, and code execution. The exact backend model ID and context-window size are not exposed in this session. ## 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>
189 lines
8.2 KiB
Markdown
189 lines
8.2 KiB
Markdown
# Dashboards, activity, and audit trails — agent access
|
|
|
|
Product map: [Dashboards, activity, and audit trails](../feature-map/activity.md).
|
|
|
|
Review date: 2026-10-12. Source commit: `f981fa3cc10cb8663a87dec60345fbff46d54d0a`.
|
|
|
|
This is a source-reviewed baseline of representative operations and known gaps.
|
|
Each capability needs operation-level review before its entire scope can be
|
|
qualified. No live agent execution is claimed. Follow the [map contract](../README.md)
|
|
for format, permission checks, evidence and maintenance.
|
|
|
|
## `overview`
|
|
|
|
Review: `baseline`.
|
|
|
|
API: `present` — representative operation IDs:
|
|
|
|
- `GET /api/companies/{companyId}/dashboard`.
|
|
|
|
Agent access: `available` — REST / native call_api / CLI dashboard.
|
|
|
|
Policy: Same company plus visibility/audit/cost/run permissions where the route requires
|
|
them.
|
|
|
|
Evidence: `source-only` — [implementation](../../server/src/routes/activity.ts#L224) at
|
|
the reviewed commit above.
|
|
|
|
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
|
credentials/run context; inspect its result and applicable persistence/attribution.
|
|
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
|
remaining operations before qualifying the whole capability.
|
|
|
|
Gaps: Dashboard data is accessible; live-work rendering and event streaming are separate
|
|
surfaces.
|
|
|
|
## `activity`
|
|
|
|
Review: `baseline`.
|
|
|
|
API: `present` — representative operation IDs:
|
|
|
|
- `GET /api/companies/{companyId}/activity`.
|
|
- `GET /api/issues/{id}/activity` (UUID or issue identifier).
|
|
|
|
Agent access: `partial` — REST / native call_api / CLI activity for company
|
|
activity. Sandbox agents can use GET issue activity through the default
|
|
[callback bridge](../../packages/adapter-utils/src/sandbox-callback-bridge.ts).
|
|
The bridge still rejects company activity and company audit routes.
|
|
|
|
Policy: Company activity requires same-company access and `company_scope:read`,
|
|
with issue visibility filtering. Issue activity requires same-company resource
|
|
access and `issue:read` for the resolved issue. The sandbox transport does not
|
|
replace those controller checks or permit activity writes.
|
|
|
|
Evidence: `source-only` — [activity routes](../../server/src/routes/activity.ts),
|
|
[agent authorization tests](../../server/src/__tests__/activity-routes.test.ts),
|
|
and [bridge tests](../../packages/adapter-utils/src/sandbox-callback-bridge.test.ts).
|
|
Issue activity transport reviewed at `89770ba707fb1ebd4cabd184eec2e7fee226e0c3`;
|
|
other operations retain the baseline source review above.
|
|
|
|
Verification: `not-run` — no live agent-credential proof. Local route and bridge
|
|
regressions pass: permitted agent issue read, denied company/resource scope,
|
|
denied writes, extra path segments, and company audit routes. With a real
|
|
sandbox agent, read an authorized issue's activity, then verify denial for an
|
|
inaccessible issue, another company, and company-wide audit.
|
|
|
|
Gaps: Audit export and raw activity creation have extra restrictions; do not
|
|
equate them with issue activity reading. Live sandbox access remains unverified.
|
|
|
|
## `runs`
|
|
|
|
Review: `baseline`.
|
|
|
|
API: `present` — representative operation IDs:
|
|
|
|
- `GET /api/companies/{companyId}/heartbeat-runs`.
|
|
- `GET /api/companies/{companyId}/live-runs`.
|
|
- `GET /api/heartbeat-runs/{runId}`.
|
|
- `GET /api/heartbeat-runs/{runId}/events`.
|
|
- `GET /api/heartbeat-runs/{runId}/log`.
|
|
- `GET /api/heartbeat-runs/{runId}/workspace-operations`.
|
|
- `GET /api/heartbeat-runs/{runId}/issues`.
|
|
- `GET /api/issues/{id}/runs`.
|
|
- `GET /api/issues/{id}/recovery-actions`.
|
|
|
|
Agent access: `available` — REST / native call_api / CLI run. Sandbox agents can
|
|
use these diagnostic GET paths through the default queue and HTTP/2
|
|
[callback bridge](../../packages/adapter-utils/src/sandbox-callback-bridge.ts).
|
|
Use the injected run credential; see the [bounded read workflow](../../skills/paperclip/references/run-diagnostics.md).
|
|
|
|
Policy: Same-company and `company_scope:read` checks apply to company run
|
|
inventory. Run content requires run/task visibility; private run list entries
|
|
may be redacted stubs. Task run/recovery reads require `issue:read`. Run-linked
|
|
tasks also pass the caller's task-read SQL predicate individually, including
|
|
activity links and the original task. Existing credential redaction remains.
|
|
Bridge admission grants no cancellation, retry, recovery resolution or
|
|
provider-trace administration authority.
|
|
|
|
Evidence: `source-only` — scoped review of `f10210990a3c9cad1a4359318388f237de3169dd`:
|
|
[run routes](../../server/src/routes/agents.ts),
|
|
[task links](../../server/src/routes/activity.ts),
|
|
[task filtering](../../server/src/services/activity.ts),
|
|
[bridge regressions](../../packages/adapter-utils/src/sandbox-callback-bridge.test.ts),
|
|
[HTTP/2 transport regressions](../../packages/adapter-utils/src/http2-bridge-server.test.ts),
|
|
and [private-run regressions](../../server/src/__tests__/heartbeat-run-privacy-routes.test.ts).
|
|
|
|
Verification: `not-run` for a deployed sandbox agent with these new routes.
|
|
Isolated regressions cover admitted GETs, denied writes/extra segments, query
|
|
forwarding, controller denials, private run stubs, and mixed public/private task
|
|
links. They do not qualify a live run. After deployment, use a real agent run to
|
|
read an authorized failure and assert denial/redaction for another company,
|
|
private tasks and restricted key modes. Do not count a skipped database suite
|
|
as successful verification.
|
|
|
|
Gaps: Telemetry/run visibility is checked independently from seeing the source task.
|
|
Company heartbeat history defaults to 200 rows and caps explicit limits at 1,000
|
|
in both the route and service. The response remains an array. Scope, visibility,
|
|
and secret redaction checks apply to the bounded result set.
|
|
Live updated-bridge admission and useful incident diagnosis remain unverified.
|
|
|
|
## `routine-audit`
|
|
|
|
Review: `baseline`.
|
|
|
|
API: `present` — representative operation IDs:
|
|
|
|
- `GET /api/routines/{id}/runs`.
|
|
|
|
Agent access: `available` — REST / native call_api / CLI routine runs.
|
|
|
|
Policy: Same company plus visibility/audit/cost/run permissions where the route requires
|
|
them.
|
|
|
|
Evidence: `source-only` — [implementation](../../server/src/routes/activity.ts#L224) at
|
|
the reviewed commit above.
|
|
|
|
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
|
credentials/run context; inspect its result and applicable persistence/attribution.
|
|
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
|
remaining operations before qualifying the whole capability.
|
|
|
|
Gaps: Routine execution history is distinct from configuration revisions and scheduling
|
|
changes.
|
|
|
|
## `timeline`
|
|
|
|
Review: `baseline`.
|
|
|
|
API: `present` — representative operation IDs:
|
|
|
|
- `GET /api/companies/{companyId}/timeline`.
|
|
|
|
Agent access: `available` — REST / native call_api.
|
|
|
|
Policy: Same company plus visibility/audit/cost/run permissions where the route requires
|
|
them.
|
|
|
|
Evidence: `source-only` — [implementation](../../server/src/routes/activity.ts#L224) at
|
|
the reviewed commit above.
|
|
|
|
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
|
credentials/run context; inspect its result and applicable persistence/attribution.
|
|
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
|
remaining operations before qualifying the whole capability.
|
|
|
|
Gaps: API exists; no dedicated timeline tool is necessary for this requirement.
|
|
|
|
## `agent-commentary`
|
|
|
|
Review: `baseline`.
|
|
|
|
API: `present` — `GET /api/companies/{companyId}/agent-commentary` and
|
|
`GET /api/companies/{companyId}/agent-commentary/{id}`.
|
|
|
|
Agent access: `restricted` — the browsing API is board-only. Agent submission
|
|
continues through the existing POST and native submit tools.
|
|
|
|
Policy: Company membership, `audit:view_agent_actions`, and source-task visibility. Counts and previews
|
|
use the same visibility predicate as full messages; cross-company IDs return 404.
|
|
Feedback stays hidden after source-task deletion, even when its task foreign key clears.
|
|
|
|
Evidence: `source-only` — [routes](../../server/src/routes/agent-commentary.ts) and
|
|
[reader](../../server/src/services/agent-commentary-reader.ts).
|
|
|
|
Verification: `not-run` for a deployed instance. Test list/detail denials with
|
|
agent credentials, another company, and an unreadable task.
|
|
|
|
Gaps: Storybook simulates the API and does not qualify deployed authorization.
|