Skip to content

Artifacts: persistent agent-maintained documents in Monitor - #479

Merged
damianloch merged 16 commits into
mainfrom
sms10221/dev-1219-aurora-canvas
Jun 10, 2026
Merged

Artifacts: persistent agent-maintained documents in Monitor#479
damianloch merged 16 commits into
mainfrom
sms10221/dev-1219-aurora-canvas

Conversation

@isiddharthsingh

@isiddharthsingh isiddharthsingh commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds Artifacts — living markdown documents Aurora maintains across runs (findings lists, cost reports, runbooks), surfaced in a new Monitor → Artifacts tab. Scheduled Actions and chat create/update them through agent tools; users can view, edit, and browse version history in the UI.

Backend

  • artifacts + artifact_versions tables with per-org RLS policies
  • Shared, Flask-free store helper for title-based upsert + versioning (reused by REST routes and agent tools so they never drift)
  • REST routes: CRUD, version history, and restore — RBAC-gated (artifacts read/write)
  • Agent tools (list / read / write) on the cloud toolbelt, plus MCP dispatch exposure
  • Discoverability is via tool descriptions only — nothing added to any system prompt

Frontend

  • Artifacts tab: master/detail with View / Edit / History modes, plus create and delete
  • Expandable per-version dropdown to read exactly what each version wrote
  • Detail and history reads cached via useQuery — re-opening an artifact and re-expanding a version are served from cache instead of refetching

Testing

  • REST CRUD full cycle; cross-org access returns 403
  • Agent tools end-to-end, including same-title re-write producing a version bump (proves cross-run persistence)
  • Architectural RBAC tests pass; tsc and ESLint clean for the changed frontend

Summary by CodeRabbit

  • New Features

    • Persistent markdown artifacts: create, view, edit, delete, per-version viewing, and restore from history.
    • Artifacts tab in Monitor with creation UI, edit/history modes, title-collision blocking, and per-item delete confirmation.
    • Client-side service and API routes for listing, fetching, creating, updating, deleting, versioning, and restoring artifacts.
    • Agent-accessible artifact tools and registry integration for programmatic list/read/write operations.
  • Chores

    • Database schema, row-level security, and RBAC updates to support tenant-scoped artifact storage and versioning.

@isiddharthsingh
isiddharthsingh requested a review from a team as a code owner June 5, 2026 03:10
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a full artifact management feature: DB schema and store helpers, Flask REST blueprint and agent tools, MCP/registry/dispatch wiring, Next.js proxy routes, a TypeScript client service, and a React UI tab with list/create/detail/history views.

Changes

Artifact Management System

Layer / File(s) Summary
Database schema and persistence foundation
server/utils/db/db_utils.py, server/services/artifacts/store.py
artifacts and artifact_versions tables with org-scoped RLS; cursor-driven create_version() and upsert_artifact_by_title() helpers for atomic operations.
Authorization and RBAC permissions
server/utils/auth/enforcer.py
Default Casbin policies grant viewer and editor roles read/write permissions to artifacts resource.
Server REST API endpoints & wiring
server/routes/artifact_routes.py, server/main_compute.py
Flask blueprint artifact_bp with GET/POST/PATCH/DELETE for artifacts, version listing/fetch/restore, org RLS context handling, audit logging, and blueprint registration.
Agent-callable artifact tools
server/chat/backend/agent/tools/artifact_tool.py
Three agent tools (list_artifacts, read_artifact, write_artifact) with Pydantic schemas, tenant-scoped DB access, input validation, and JSON responses.
Agent tool registration and MCP dispatch
server/chat/backend/agent/tools/cloud_tools.py, server/aurora_mcp/registry.py, server/aurora_mcp/dispatch.py
Conditional import and registration of artifact tools into cloud tools; dispatch registry adds artifact entries and advertises query_keys for query-string forwarding.
Client-side API service wrapper
client/src/lib/services/artifacts.ts
TypeScript service defining artifact domain types (summaries, versions, details) and wrapping REST calls with normalized error handling and 404→null semantics.
Next.js API route proxy handlers
client/src/app/api/artifacts/route.ts, client/src/app/api/artifacts/[id]/route.ts, client/src/app/api/artifacts/[id]/versions/route.ts, client/src/app/api/artifacts/[id]/versions/[versionId]/route.ts, client/src/app/api/artifacts/[id]/versions/[versionId]/restore/route.ts
Five proxy modules that resolve async route params and delegate to backend via forwardRequest with method-specific failure messages.
Client-side artifacts tab and views
client/src/app/monitor/components/artifacts-tab.tsx, client/src/app/monitor/page.tsx
React ArtifactsTab implementing list, create, and detail (view/edit/history) modes with lazy version loading, edit buffering, delete/restore flows, and tab integration.
sequenceDiagram
  participant Client
  participant NextAPI as Next.js API
  participant ArtifactService as Flask artifact_bp
  participant Postgres as Postgres DB

  Client->>NextAPI: HTTP request (GET/POST/PATCH/DELETE /api/artifacts...)
  NextAPI->>ArtifactService: forwardRequest to /api/artifacts[...]
  ArtifactService->>Postgres: SELECT / INSERT / UPDATE / create_version / restore
  Postgres-->>ArtifactService: rows / new version id
  ArtifactService-->>NextAPI: JSON response
  NextAPI-->>Client: proxied HTTP response
Loading

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Possibly related PRs:

    • Arvo-AI/aurora#366: Related changes to build_action_prompt and the Actions executor that introduce living-document prompt behavior.
  • Suggested reviewers:

    • damianloch
    • Zarlanx
    • OlivierTrudeau

🐰 From schema roots I nibble fine,
I stitch each version, leaf and line.
A route, a tool, a UI bright,
Restore and save through day and night,
Hooray — the artifacts take flight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature being added: persistent agent-maintained Markdown documents (Artifacts) now surfaced in the Monitor UI.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sms10221/dev-1219-aurora-canvas

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/app/monitor/components/artifacts-tab.tsx`:
- Around line 54-56: The artifacts fetch currently defaults to an empty array
when the query fails which makes the UI show "No artifacts yet." and breaks
overwrite checks; update the useQuery handling around the call to useQuery<{
artifacts: ArtifactSummary[] }> (the destructured data, isLoading, mutate) and
any downstream usage of data.artifacts/existingTitles so that: 1) you detect and
handle query errors (use isError or error from useQuery) and render an explicit
error state instead of treating missing data as an empty list; 2) do not default
artifacts to [] for UI or for create/overwrite guards until the query is
successful (use a guard like if (!data || isError) before deriving
existingTitles); and 3) keep the loading behavior via isLoading; update the
render branches around the artifacts list (and the create flow that references
existingTitles) to disable or show an error when the query failed so overwrite
checks remain correct.

In `@client/src/lib/services/artifacts.ts`:
- Around line 24-31: Remove the userId field from the ArtifactVersion interface
in client/src/lib/services/artifacts.ts (the ArtifactVersion type) and update
all client-side usages that reference ArtifactVersion.userId (including
functions, API response handling, mappers, and tests) to stop expecting or
accessing user identity; adjust any deserialization or type assertions that
assumed a userId and rely on server-side identity resolution instead, and
run/typecheck to fix any compilation errors by removing or replacing references
to userId with server-provided metadata fields if needed.
- Around line 52-60: The current getArtifact function (and the similar function
at lines 96-105) swallows all non-404 errors and returns null/empty data, which
hides real API failures; change the catch blocks to only return null when the
caught error is an ApiError with status 404, and rethrow or propagate other
errors (i.e., throw error) so callers/UI can surface real API errors; locate the
catch in getArtifact (uses apiGet and ApiError) and the analogous catch in the
other artifact/history function and replace the unconditional console.error +
return null with conditional logic that returns null for 404 and throws the
error for any other status.

In `@server/chat/backend/agent/tools/artifact_tool.py`:
- Around line 38-77: list_artifacts currently opens an admin DB connection
before verifying the caller has artifact read access; add an upfront RBAC check
(before calling db_pool.get_admin_connection()) to verify the user has the
artifacts.read permission and return an error JSON if not authorized. Do the
same pattern for read_artifact (check artifacts.read) and write_artifact (check
artifacts.write) entry points—call your existing permission helper (e.g.,
has_permission or check_permission) with user_id and the appropriate permission
string, and bail early if the check fails so no admin DB connection or
set_rls_context is performed.

In `@server/routes/artifact_routes.py`:
- Around line 129-141: The SQL query in cursor.execute is selecting a.content
even though the endpoint calls _serialize_artifact with include_content=False,
causing unnecessary I/O and memory usage; update the SELECT to omit a.content
(or replace it with NULL/'' as a placeholder) so rows do not include full
document content, then ensure _serialize_artifact is still called with
include_content=False (same call site) to keep list responses lightweight.

In `@server/services/artifacts/store.py`:
- Around line 30-37: The INSERT currently uses (SELECT
COALESCE(MAX(version_number), 0) + 1 FROM artifact_versions WHERE artifact_id =
%s) which is race-prone; wrap the allocate-and-insert in a DB transaction and
serialize concurrent allocs for the same artifact by acquiring a lock (e.g. call
SELECT pg_advisory_xact_lock(%s) with artifact_id or SELECT id FROM artifacts
WHERE id=%s FOR UPDATE) before computing MAX(version_number) and performing the
INSERT into artifact_versions, and ensure there is a unique constraint on
(artifact_id, version_number) so any rare race will surface and can be retried;
update the code that runs this SQL (the store logic around
artifact_versions/artifact_id/version_number) to begin a transaction, acquire
the lock, compute MAX+1, insert, and commit.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3fab6e51-2f9b-4987-b2ba-299a5f4b22b5

📥 Commits

Reviewing files that changed from the base of the PR and between fe957de and 34957d3.

📒 Files selected for processing (18)
  • client/src/app/api/artifacts/[id]/route.ts
  • client/src/app/api/artifacts/[id]/versions/[versionId]/restore/route.ts
  • client/src/app/api/artifacts/[id]/versions/[versionId]/route.ts
  • client/src/app/api/artifacts/[id]/versions/route.ts
  • client/src/app/api/artifacts/route.ts
  • client/src/app/monitor/components/artifacts-tab.tsx
  • client/src/app/monitor/page.tsx
  • client/src/lib/services/artifacts.ts
  • server/aurora_mcp/dispatch.py
  • server/aurora_mcp/registry.py
  • server/chat/backend/agent/tools/artifact_tool.py
  • server/chat/backend/agent/tools/cloud_tools.py
  • server/main_compute.py
  • server/routes/artifact_routes.py
  • server/services/artifacts/__init__.py
  • server/services/artifacts/store.py
  • server/utils/auth/enforcer.py
  • server/utils/db/db_utils.py

Comment thread client/src/app/monitor/components/artifacts-tab.tsx Outdated
Comment thread client/src/lib/services/artifacts.ts
Comment thread client/src/lib/services/artifacts.ts
Comment thread server/chat/backend/agent/tools/artifact_tool.py
Comment thread server/routes/artifact_routes.py
Comment thread server/services/artifacts/store.py
…nent, hoist duplicate literals to constants, use logging.exception
…ten list query, serialize version allocation
Comment thread client/src/lib/services/artifacts.ts Outdated
Comment thread client/src/lib/services/artifacts.ts
Comment thread client/src/lib/services/artifacts.ts Outdated
Comment thread server/chat/backend/agent/tools/artifact_tool.py
Comment thread server/services/actions/executor.py Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/services/actions/executor.py`:
- Around line 178-191: The current guard only checks for the literal substring
"artifact" before injecting the persistence block, which misses other
user-steering phrases; update the condition around action["instructions"] in
executor.py so it scans a small set of persistence keywords (e.g., "artifact",
"read_artifact", "write_artifact", "living document", "runbook", "persist across
runs") against action["instructions"].lower() and only injects the Maintain a
Living Document block when none of those keywords are present; keep the existing
block contents (using title = action["name"] and the
read_artifact/write_artifact guidance) and ensure the check is applied where the
parts list is appended.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 20ef3383-b71d-4ec0-87b1-5e250840b4c4

📥 Commits

Reviewing files that changed from the base of the PR and between f595da8 and 32ab7ff.

📒 Files selected for processing (1)
  • server/services/actions/executor.py

Comment thread server/services/actions/executor.py Outdated
…roaden user-steering detection beyond the bare artifact substring
Comment thread server/services/actions/executor.py Outdated
@sonarqubecloud

sonarqubecloud Bot commented Jun 9, 2026

Copy link
Copy Markdown

@damianloch
damianloch merged commit e492b2a into main Jun 10, 2026
14 checks passed
@damianloch
damianloch deleted the sms10221/dev-1219-aurora-canvas branch June 10, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants