Project Reports

Versioned HTTPS JSON API for ingesting project status reports. Canonical ingestion path — MCP reads the same services later.

Overview

Agents, workers, CI jobs, and Mac clients POST a Project Report JSON document to POST /api/v1/project-reports. ProjectMind validates it against a published JSON Schema, stores the raw payload, normalizes queryable rows, and updates a per-environment latest pointer. Historical reports are never deleted.

The versioned HTTPS API is the canonical ingestion interface. Future MCP tools are read-only facades over the same application services — do not treat MCP as the write path.

Project manifest (imemory.project.yaml)

Connected repositories declare capabilities, commands, protected paths, verification, and autonomy templates in imemory.project.yaml. ProjectMind validates the manifest, caches the last valid snapshot, and drives the improvement loop from configuration — not from project-name branches.

  • Schema: manifest-schema.json
  • Example: examples/imemory.project.yaml (sample-project fixture)
  • Autonomy templates: observe-only, propose-only, manual-execution, safe-pull-request, low-risk-autonomous, finance-safe, privacy-sensitive
  • Category policies (backend-enforced): product may code; relationship/financial categories route to task hub / briefing / user-action queues and never the coding agent.

Connect a new project (no ProjectMind code change)

  1. Create the project in ProjectMind and connect its Git repository (configure a runtime project path).
  2. Add imemory.project.yaml and AGENTS.md to the repository.
  3. Refresh/load the manifest from project settings or the local Mac agent path.
  4. Mint a project-report credential and POST the first report.
  5. Select an autonomy template (or declare it in the manifest).
  6. Confirm readiness: manifest valid, reporting configured, required commands present, coding/verification capabilities as needed.

Rule: new project = configuration and contract implementation. New platform capability = ProjectMind code change.

Quick start

  1. Create a project report credential (token prefix impr_) with scope project-reports:write for your project. From the ProjectMind repo: npm run mint:project-report-credential -- --project-id <uuid> --name "reporter".
  2. Download the minimal example and set project.id to your ProjectMind project UUID.
  3. POST to /api/v1/project-reports with the bearer token.
cURL
curl -X POST https://your-imemory-host/api/v1/project-reports \
  -H "Authorization: Bearer impr_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d @minimal.json

Authentication

Use a per-project credential. Pass the token as Authorization: Bearer impr_… or x-api-key. Tokens are stored as SHA-256 hashes only. Required write scope: project-reports:write. Credentials may expire or be revoked; expired/revoked tokens are rejected.

The credential is bound to a single project. Submitting a report whose project.id does not match returns 403.

Complete schema reference

Generated from the canonical JSON Schema (no hand-maintained field list). Unknown root-level properties are rejected; unknown keys inside extensions are accepted.

PathTypeReqDescription
schemaVersionconst "1.0"yesReport schema version. Currently only "1.0" is accepted.
reportIdstringyesClient-generated idempotency key for this report. Prefer UUIDv4.
generatedAtstring (date-time)yesISO-8601 timestamp when the report was generated.
projectobjectyes
project.idstringyesProjectMind project UUID (or stable external id mapped to a project).
project.namestringyes
project.environmentenum: "production" | "staging" | "development" | "test" | "preview"yes
project.statusenum: "healthy" | "degraded" | "unhealthy" | "unknown" | "maintenance"yes
project.slugstring
project.descriptionstring
project.versionstringApplication or release version string.
project.urlstringPrimary public URL for the project.
summaryobject
summary.headlinestring
summary.bodystring
summary.highlightsarray<string>
healthobject
health.scorenumberOptional self-reported health score (0–100). ProjectMind does not compute this.
health.statusenum: "healthy" | "degraded" | "unhealthy" | "unknown" | "maintenance"
health.checkedAtstring (date-time)
health.componentsarray<object>
health.components[].namestringyes
health.components[].statusenum: "healthy" | "degraded" | "unhealthy" | "unknown" | "maintenance"yes
health.components[].messagestring
metricsarray<object>
metrics[].keystringyes
metrics[].valuenumberyes
metrics[].unitstring
metrics[].timestampstring (date-time)
metrics[].labelsobject
deploymentsarray<object>
deployments[].idstringyes
deployments[].statusenum: "pending" | "building" | "deploying" | "success" | "failed" | "rolled_back" | "cancelled"yes
deployments[].timestampstring (date-time)yes
deployments[].environmentenum: "production" | "staging" | "development" | "test" | "preview"
deployments[].versionstring
deployments[].urlstring
deployments[].commitShastring
deployments[].messagestring
issuesarray<object>
issues[].idstringyes
issues[].titlestringyes
issues[].severityenum: "critical" | "high" | "medium" | "low" | "info"yes
issues[].statusenum: "open" | "acknowledged" | "resolved" | "ignored"
issues[].descriptionstring
issues[].detectedAtstring (date-time)
issues[].resolvedAtstring,null (date-time)
issues[].sourcestring
issues[].urlstring
issues[].categoryenum: "product" | "platform_reliability" | "test_coverage" | "documentation" | "relationship_action" | "financial_insight" | "financial_action" | "operational_action" | "user_action" | "security_action" | "policy_change" | "credential_change" | "audit_change" | "destructive_data_change" | "production_deployment" | "external_communication" | "data_review"product → coding loop; relationship_action / financial_insight / financial_action → non-coding workflows only.
issues[].kindenum: "follow_up" | "upcoming_event" | "overdue_commitment" | "data_review" | "other" | "cash_flow" | "spend_anomaly" | "recurring_bill" | "safe_to_spend" | "liability" | "investment" | "coverage_gap" | "review_bill" | "reconnect_account" | "dispute_charge" | "cancel_subscription" | "transfer" | "payment" | "trade" | "apply_credit"Optional subtype for relationship_action, financial_insight, or financial_action issues.
issues[].priorityenum: "low" | "medium" | "high" | "urgent"
issues[].dueAtstring (date-time)
issues[].personRefstringOpaque internal person reference. Never a production person record payload.
issues[].suggestedTaskTitlestring
issues[].explanationstring
issues[].insightTypeenum: "cash_flow" | "spend_anomaly" | "recurring_bill" | "safe_to_spend" | "liability" | "investment" | "coverage_gap" | "other"
issues[].factKindenum: "observed_fact" | "inference" | "recommendation" | "incomplete_data"
issues[].coveragePeriodStartstring (date-time)
issues[].coveragePeriodEndstring (date-time)
issues[].confidencenumber
issues[].supportingDataRefstring
issues[].briefingEligibleboolean
issues[].voiceEligibleboolean
issues[].actionTypeenum: "review_bill" | "reconnect_account" | "dispute_charge" | "cancel_subscription" | "transfer" | "payment" | "trade" | "apply_credit" | "data_review" | "other"
issues[].supportingInsightRefstring
issues[].dataCoverageStatementstring
issues[].estimatedEffectstring
issues[].riskenum: "low" | "medium" | "high" | "critical"
issues[].requiresConfirmationboolean
issues[].deepLinkstring
relationshipActionsarray<object>My People relationship-action candidates. Never enter the coding-agent lifecycle.
relationshipActions[].idstringyes
relationshipActions[].titlestringyes
relationshipActions[].descriptionstring
relationshipActions[].suggestedTaskTitlestring
relationshipActions[].priorityenum: "low" | "medium" | "high" | "urgent"
relationshipActions[].dueAtstring (date-time)
relationshipActions[].personRefstringOpaque internal person reference only.
relationshipActions[].evidenceRefstring
relationshipActions[].kindenum: "follow_up" | "upcoming_event" | "overdue_commitment" | "data_review" | "other"
relationshipActions[].sourcestring
financialInsightsarray<object>MoneySprout financial-insight summaries. Aggregated only — never enter the coding-agent lifecycle.
financialInsights[].idstringyes
financialInsights[].titlestringyes
financialInsights[].explanationstring
financialInsights[].insightTypeenum: "cash_flow" | "spend_anomaly" | "recurring_bill" | "safe_to_spend" | "liability" | "investment" | "coverage_gap" | "other"
financialInsights[].factKindenum: "observed_fact" | "inference" | "recommendation" | "incomplete_data"
financialInsights[].coveragePeriodStartstring (date-time)
financialInsights[].coveragePeriodEndstring (date-time)
financialInsights[].confidencenumber
financialInsights[].supportingDataRefstring
financialInsights[].briefingEligibleboolean
financialInsights[].voiceEligibleboolean
financialInsights[].deepLinkstring
financialInsights[].sourcestring
financialActionsarray<object>MoneySprout financial-action suggestions. Never execute money movement; never enter the coding-agent lifecycle.
financialActions[].idstringyes
financialActions[].titlestringyes
financialActions[].explanationstring
financialActions[].actionTypeenum: "review_bill" | "reconnect_account" | "dispute_charge" | "cancel_subscription" | "transfer" | "payment" | "trade" | "apply_credit" | "data_review" | "other"
financialActions[].supportingInsightRefstring
financialActions[].dataCoverageStatementstring
financialActions[].estimatedEffectstring
financialActions[].riskenum: "low" | "medium" | "high" | "critical"
financialActions[].requiresConfirmationboolean
financialActions[].deepLinkstring
financialActions[].sourcestring
capabilitiesarray<string>Self-reported project capabilities (e.g. contact-sync, reminders).
tasksarray<object>
tasks[].idstringyes
tasks[].titlestringyes
tasks[].statusenum: "todo" | "in_progress" | "blocked" | "done" | "cancelled"yes
tasks[].priorityenum: "low" | "medium" | "high" | "urgent"
tasks[].assigneestring
tasks[].dueAtstring (date-time)
tasks[].urlstring
agentobject
agent.idstring
agent.namestring
agent.kindenum: "mac-agent" | "coding-agent" | "background-worker" | "mobile-app" | "saas" | "ci" | "other"
agent.versionstring
agent.platformstring
agent.hostnamestring
linksobject
links.dashboardstring
links.repositorystring
links.docsstring
links.logsstring
links.extraobject
extensionsobjectVendor-specific or experimental fields. Unknown keys inside extensions are accepted.

Examples

Valid examples live under spec/examples/ and are validated in CI: minimal, full, SaaS, mobile app, background worker, Mac agent, and coding agent.

API reference

Generated from the OpenAPI document.

MethodPathAuthSummary
POST/api/v1/project-reportsProject report credentialIngest a project report
GET/api/v1/projectsProject report credentialList projects visible to the credential
GET/api/v1/projects/{projectId}Project report credentialGet a project summary with latest report pointer
GET/api/v1/projects/{projectId}/reports/latestProject report credentialGet the latest report for a project
GET/api/v1/projects/{projectId}/reportsProject report credentialList historical reports for a project
GET/api/v1/project-report-schemaNoneDownload the Project Report JSON Schema
GET/openapi.jsonNoneOpenAPI document (JSON)
GET/openapi.yamlNoneOpenAPI document (YAML)

Rate limit: 60 requests / minute per credential. Success shape for ingest: { accepted, reportId, projectId, schemaVersion, receivedAt }.

Validation rules

  • Body must match JSON Schema draft 2020-12; additionalProperties: false at the root (and nested objects except extensions).
  • Only schemaVersion: "1.0" is accepted.
  • Enums enforced for status, environment, severity, task status, deployment status.
  • Timestamps must be ISO-8601 date-time.
  • Maximum body size: 512 KiB.

Retry & idempotency

Clients should set a stable reportId (and optionally Idempotency-Key). Replaying the same id with the same payload returns 202 with duplicate: true. A different payload for the same id returns 409. Retry with exponential backoff on 429 / 5xx — do not retry 401, 403, or 422.

TypeScript / Python / cURL

TypeScript (@imemory/project-reporter)
import { IMemoryProjectReporter } from "@imemory/project-reporter";

const reporter = new IMemoryProjectReporter({
  baseUrl: "https://your-imemory-host",
  token: process.env.IMEMORY_PROJECT_REPORT_TOKEN!,
});

await reporter.submit({
  project: {
    id: "11111111-1111-1111-1111-111111111111",
    name: "Example App",
    environment: "production",
    status: "healthy",
  },
});
Python
import json, urllib.request, uuid, datetime

token = "impr_YOUR_TOKEN"
body = {
  "schemaVersion": "1.0",
  "reportId": str(uuid.uuid4()),
  "generatedAt": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.000Z"),
  "project": {
    "id": "11111111-1111-1111-1111-111111111111",
    "name": "Example App",
    "environment": "production",
    "status": "healthy",
  },
}
req = urllib.request.Request(
  "https://your-imemory-host/api/v1/project-reports",
  data=json.dumps(body).encode(),
  headers={
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json",
    "Idempotency-Key": body["reportId"],
  },
  method="POST",
)
print(urllib.request.urlopen(req).read().decode())
cURL
curl -X POST https://your-imemory-host/api/v1/project-reports \
  -H "Authorization: Bearer impr_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d @minimal.json

MCP architecture

MCP is not the primary write interface for project reports. Planned read-only MCP tools (list_projects, get_project, get_latest_project_report, get_project_metrics, get_project_issues, get_project_timeline, compare_projects, generate_project_briefing, find_projects_requiring_attention) call the same internal services as this REST API. Write tools will not be added for report ingestion.

Facades live in src/lib/project-reports/mcp-facade.server.ts.

Changelog

  • 1.0.0 — Initial Project Reports API, schema, OpenAPI, docs, and SDK scaffold.

Downloads

See also API docs and MCP docs.