Skip to content

feat(collector): app-owner vs M2M customer identity#70

Open
eliteprox wants to merge 1 commit into
mainfrom
feat/owner-m2m-customer-identity
Open

feat(collector): app-owner vs M2M customer identity#70
eliteprox wants to merge 1 commit into
mainfrom
feat/owner-m2m-customer-identity

Conversation

@eliteprox

Copy link
Copy Markdown
Collaborator

Summary

  • Port the pymthouse collector identity contract: app-owner wire subjects app_…:owner:{users.id} map to CloudEvent subject / customer key = bare {users.id}; M2M managed users keep compound app_…:external_user_id unchanged
  • Bootstrap (bootstrap.sh / bootstrap.ps1) gains an owner command (and customer auto-delegates when external_user_id starts with owner:)
  • Add openmeter-collector/identity Go helpers + unit tests for the customer-key contract
  • Document the two customer shapes in root and provision READMEs

Closes #69

Test plan

  • cd openmeter-collector/identity && go test ./... -count=1
  • bash -n openmeter-collector/provision/bootstrap.sh
  • Manual: ingest a Kafka event with auth_id=app_x:owner:{uuid} → CloudEvent subject={uuid}, usage_subject_type=app_owner
  • Manual: ingest auth_id=app_x:user-1subject=app_x:user-1 (unchanged)
  • Manual: ./bootstrap.sh owner <uuid> "App Owner" creates customer keyed by bare uuid
  • Manual: ./bootstrap.sh customer demo-client demo-user still creates compound key

Port the pymthouse collector identity contract: strip owner: wire subjects
to bare {users.id} CloudEvent subjects, keep M2M compound keys unchanged,
and teach bootstrap to provision shared owner customers.
Copilot AI review requested due to automatic review settings July 17, 2026 17:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the OpenMeter collector + provisioning tooling to support two customer identity shapes: app-owner usage subjects that resolve to a shared bare user-id wallet, and M2M/managed-user usage subjects that remain compound client_id:external_user_id keys.

Changes:

  • Update openmeter-collector/collector.yaml to map auth_id=app_…:owner:{users.id} to CloudEvent subject={users.id} (and add openmeter_customer_key / eth_usd_price, plus ceil for USD micros).
  • Extend provisioning scripts (bootstrap.sh/.ps1) with an owner command and delegation from customer when external_user_id starts with owner:.
  • Add Go helpers + tests under openmeter-collector/identity documenting/testing the customer key contract; update root + provision docs.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Documents the app-owner vs M2M subject/customer-key contract and provides example egress events.
openmeter-collector/provision/README.md Updates provisioning instructions + documents the two customer shapes and their keys.
openmeter-collector/provision/bootstrap.sh Adds owner provisioning and refactors customer creation to a key-based helper.
openmeter-collector/provision/bootstrap.ps1 PowerShell parity for owner provisioning and key-based customer helper.
openmeter-collector/identity/go.mod Introduces a small standalone Go module for identity contract helpers.
openmeter-collector/identity/customer_key.go Implements owner vs M2M key derivation helpers.
openmeter-collector/identity/customer_key_test.go Adds unit tests for owner vs M2M key behavior.
openmeter-collector/collector.yaml Implements owner subject normalization and adds extra event fields + USD micros rounding behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +125 to +136
# Owner wallet: wire usage_subject is owner:{users.id}; CE subject = bare id.
# M2M end-users: meter subject = full compound auth_id.
let is_owner_subject = $usage_subject_parsed.index_of("owner:") == 0
let usage_subject_type = if $is_owner_subject { "app_owner" } else { "external_user_id" }
let owner_bare_id = if $is_owner_subject {
$usage_subject_parsed.slice("owner:".length())
} else {
$usage_subject_parsed
}
let openmeter_subject = if $is_owner_subject { $owner_bare_id } else { $auth_id }
let openmeter_customer_key = $openmeter_subject
let usage_subject_out = if $is_owner_subject { $owner_bare_id } else { $usage_subject_parsed }
"gateway_request_id": $data.request_id,
"auth_id": $auth_id,
"openmeter_customer_key": $openmeter_customer_key,
"eth_usd_price": $eth_usd.string(),
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.

collector + bootstrap: support app-owner vs M2M customer identity (owner: wire subject)

2 participants