Summary
Platform-side infrastructure required for the meter package shipped in SDK issue #13. The SDK async-invokes a platform-owned Lambda with usage events; the platform must deploy the Lambda, enforce the trust boundary, and pick a storage backend.
What the SDK expects (from merged PR #78)
Security-critical (hard requirements)
-
Meter Lambda function — accepts `meter.Event` JSON, reads invoker identity, writes to storage.
-
IAM scoping — module's Lambda execution role gets `lambda:InvokeFunction` on the exact meter ARN only, never `*`. A rogue module must not be able to enumerate/invoke sibling modules' meter ARNs.
-
Invoker identity verification — the meter Lambda MUST read `context.FunctionArn` (or `context.InvokedFunctionArn`) from the AWS invocation context and cross-check it against a platform-owned `(invoker_arn → authorized_app_ids)` mapping. The payload's `appIdHint`, `moduleIdHint`, `recordedAtHint` are hints, never trusted for billing attribution.
-
EventID dedup — persist `eventId` in a short-TTL store (24-72h) to reject Lambda async retries. ReceipientId replay = double billing.
-
Timestamp authority — replace `recordedAtHint` with server receive time. MUST reject events where `recordedAtHint` is >60 seconds off receive time (backdating would corrupt billing period attribution).
-
Deploy ordering — `(invoker_arn → app_ids)` mapping MUST be updated and propagated BEFORE the module's new ARN goes live. Reverse ordering drops the first N events silently.
-
Staging discipline — prod meter ARN MUST NOT be reachable from staging modules. Defense-in-depth: the prod meter Lambda should reject invocations where `context.InvokedFunctionArn`'s account ID is not in an environment-tagged allowlist.
Storage choice (platform decision)
- Partition/sort key: `(module_id, metric, recorded_at)` where `recorded_at` is server-assigned. `EventID` is dedup-only, NOT primary key (UUID-random → write amplification).
- Retention split:
- Dedup window: 24-72h, short-TTL store (Redis / DynamoDB TTL)
- Billing events: 7 years minimum (tax/audit). Cold tier OK — ClickHouse + S3, Timestream magnetic store, or Parquet in S3 + Athena. Different data store from dedup.
- Fraud detection: platform-side rate limiting + anomaly bounds on value ranges. Out of SDK scope.
Operational
- Monitoring: per-module event rate, dedup hit rate, reject rate (stale timestamps, unknown ARNs)
- DLQ for malformed payloads
- Developer-visible billing dashboard
Files / systems affected
- New Lambda function (platform repo)
- IAM policy templates
- Platform-owned billing DB schema + ingest code
- Invoker→app mapping service
- Platform deployment automation (staging discipline enforcement)
Blocking
- Billing v1 cannot go live without this. The SDK is ready; the ingest side is not.
Origin
Documented in PR #78 description + `/Users/owo/.claude/plans/functional-waddling-planet.md`; never filed as a trackable platform issue.
Summary
Platform-side infrastructure required for the meter package shipped in SDK issue #13. The SDK async-invokes a platform-owned Lambda with usage events; the platform must deploy the Lambda, enforce the trust boundary, and pick a storage backend.
What the SDK expects (from merged PR #78)
Security-critical (hard requirements)
Meter Lambda function — accepts `meter.Event` JSON, reads invoker identity, writes to storage.
IAM scoping — module's Lambda execution role gets `lambda:InvokeFunction` on the exact meter ARN only, never `*`. A rogue module must not be able to enumerate/invoke sibling modules' meter ARNs.
Invoker identity verification — the meter Lambda MUST read `context.FunctionArn` (or `context.InvokedFunctionArn`) from the AWS invocation context and cross-check it against a platform-owned `(invoker_arn → authorized_app_ids)` mapping. The payload's `appIdHint`, `moduleIdHint`, `recordedAtHint` are hints, never trusted for billing attribution.
EventID dedup — persist `eventId` in a short-TTL store (24-72h) to reject Lambda async retries. ReceipientId replay = double billing.
Timestamp authority — replace `recordedAtHint` with server receive time. MUST reject events where `recordedAtHint` is >60 seconds off receive time (backdating would corrupt billing period attribution).
Deploy ordering — `(invoker_arn → app_ids)` mapping MUST be updated and propagated BEFORE the module's new ARN goes live. Reverse ordering drops the first N events silently.
Staging discipline — prod meter ARN MUST NOT be reachable from staging modules. Defense-in-depth: the prod meter Lambda should reject invocations where `context.InvokedFunctionArn`'s account ID is not in an environment-tagged allowlist.
Storage choice (platform decision)
Operational
Files / systems affected
Blocking
Origin
Documented in PR #78 description + `/Users/owo/.claude/plans/functional-waddling-planet.md`; never filed as a trackable platform issue.