Skip to content

Metarecord Service (MRS)

MRS — Metarecord Service

Opaque tenant-scoped object store. Metadata in DynamoDB; content in S3 (versioned, non-current retained 365d). Tenant surface is API Gateway (session required); maintenance ops are operator-only direct Lambdas (IAM-gated). Pagination default 8 (clamp 1–256). Contract-only: no internal infra details.

Surface map

  • API Gateway: base https://api.g3nretailstack.com/mrs; router trims stage and prefixes /mrs when missing, so use the custom-domain base. Tenant routes require either x-session-guid (human USM session) or x-api-key (USM service-account API key).
  • Auth: must supply orgcode; optional cccode. Caller must belong to the org (owner or active member); non-associated callers receive 404 not-found (anti-enumeration). Status values: active, pending_upload, doomed (terminal). Once status=doomed, tenant mutations are rejected (409 with error.major.tag="doomed"). TTL doom_at auto-dooms; default queries return active only unless include_doomed/status filter provided.
  • Container: normalized to lowercase and must match ^[a-z][a-z0-9_-]{1,79}$ (2..80 chars).
  • Content tiers: inline JSON only when content_type=application/json and payload ≤256 KB (no gzip). All other uploads use presigned S3; gzip mandatory; hard cap 128 MB. content_md5 on presign/complete is the hex MD5 of the gzip payload (CLI computes this for you). Downloads via presigned GET except inline JSON.
  • Tags: [0-9A-Za-z]{1,128}, no spaces, cap 20 per record, canonical uppercase; tag queries filter by PK+SK prefix (one tag at a time).
  • Idempotency: optional idempotency_key (ASCII ≤128) scoped to container+record_id (if provided) or container+idempotency_key (auto-id). Window 24h; replays return the first response (errors included).
  • CLI: g3n mrs ... uses API Gateway for tenant operations and direct Lambda for operator-only ops (mrs reconcile, mrs tag-scrub, mrs cleanup). Operator ops require --profile (IAM) plus --orgcode and --container; supports --next-token for pagination. Auto-selects inline vs presign and gzips presign uploads (computes size, hex MD5 of gzip, enforces 128 MB cap, and calls complete).
  • MCP: protocol doc https://mcp.g3nretailstack.com/mrs/PROTOCOL.md (mirrored here when published).
  • OpenAPI: https://doc.g3nretailstack.com/mrs/openapi.yaml
  • Gzip + MD5 helpers: /common/snippets/mrs-gzip-md5-node.js and /common/snippets/mrs-gzip-md5-python.py
  • Jobs: scheduled sweep/tag-scrub/compactor/cleanup are internal (EventBridge → Lambda). Cleanup retention defaults to 90d (MRS_CLEANUP_RETENTION_DAYS).
  • Role matrix: /common/role-matrix.html
  • Troubleshooting (404): /common/troubleshooting.html
  • Headers and identity cheat sheet: /common/headers-identity.html

Responses use { success, data?, error?, build, stats? } with stats including latency, bandwidth in/out, org/cc/session context when provided. Content is never returned in events; presigned URLs are used for data transfer.

Quick start

  1. Create/put: call /mrs/record with metadata and inline payload (≤256 KB JSON) or request presign for larger/other content. If presigned, upload gzip payload to S3, then record/complete with size/etag/version/md5 (hex MD5 of the gzip body). CLI inline: g3n mrs put --inline-payload-file payload.json --content-type application/json --container demo --orgcode ORG ...; presign: g3n mrs put --file blob.bin --content-type application/octet-stream --container demo --orgcode ORG ... (CLI gzips, computes size + hex MD5, enforces 128 MB cap, and completes automatically).
  2. Fetch: /mrs/record returns inline JSON or a presigned GET handle; /mrs/record/meta for metadata only.
  3. Manage: tag/add|remove, ttl/set, doom, head, and list with filters (container/org/cc/tag/status/prefix, include_doomed).
  4. Ops: tag-scrub (remove doomed from tag index), reconcile (DDB↔S3), cleanup (stale fan-out/rollups) are operator-only direct Lambdas (org-scoped via orgcode); scheduled sweeps run via jobs.

Examples

  • Inline (≤256 KB JSON, no gzip): g3n mrs put --profile g3nretailstack --session-guid $SESSION --orgcode $ORG --container demo --record-id note-1 --inline-payload-file note.json --content-type application/json
  • Presign (gzip required): g3n mrs put --profile g3nretailstack --session-guid $SESSION --orgcode $ORG --container demo --record-id blob-1 --file big.bin --content-type application/octet-stream (CLI gzips, computes hex MD5 of gzip, enforces 128 MB cap, completes upload).
  • Error example (missing gzip on >256 KB): HTTP 400 with error.major.tag="gzip-required" and success=false in the envelope.

Error tags (representative) invalid-session, invalid-tag, inline-too-large, missing-size, size-mismatch, too-large, unsupported-content-type, gzip-required, missing-content-md5, invalid-content-md5, md5-missing, md5-mismatch, not-found, doomed, invalid-status, idempotency-conflict, throttled, internal-error.