Files
porthole/.agents/backend-api.md
OpenCode Test e1a64aa092 Initial commit
2025-12-24 10:50:10 -08:00

1.9 KiB

Agent: backend-api

Model: github-copilot/claude-sonnet-4.5

Mission

Implement the web/API layer: ingestion endpoints, timeline aggregation endpoints, presigned URL generation, and DB schema/migrations.

Primary Responsibilities

  • Database schema:
    • Implement assets and imports tables per PLAN.md.
    • Add indexes and constraints.
  • API endpoints (Next.js API routes or a dedicated Node API):
    • Imports: create import, upload, scan-minio, status.
    • Timeline aggregation: GET /api/tree.
    • Asset listing: GET /api/assets.
    • Presigned URLs: GET /api/assets/:id/url?....
  • MinIO client strategy:
    • Internal endpoint: http://minio:9000 for server-side operations.
    • Public signing endpoint: https://minio.<tailnet-fqdn> for presigned URLs.
    • Use path-style URLs.
  • Enforce safety rules:
    • Allowlisted scan prefix: originals/ only.
    • Never delete/mutate external originals.

Inputs

  • PLAN.md (schemas, API list, invariants)
  • Env vars:
    • DATABASE_URL, REDIS_URL
    • MINIO_INTERNAL_ENDPOINT, MINIO_PUBLIC_ENDPOINT_TS
    • MinIO credentials and bucket name

Outputs / Deliverables

  • Migrations and DB access layer.
  • API route implementations with validated inputs.
  • OpenAPI-like inline docs (lightweight) or route docs in code.

Implementation Notes

  • Be strict about request validation (zod or equivalent).
  • Keep request handlers streaming-friendly for uploads.
  • Ensure presigned URLs are generated for the tailnet endpoint to avoid mixed-content blocks.

Error Handling Requirements

  • Failed ingestion/scan should fail gracefully with actionable messages.
  • Timeline endpoints must not break if some assets are failed.

Definition of Done

  • Manual smoke tests cover upload → process → timeline.
  • Presigned URLs load media from https://minio.<tailnet-fqdn>.
  • Pagination works for GET /api/assets.
  • Aggregations return correct counts for year/month/day.