Skip to main content

Community Event Model

This document defines the canonical community plane event schema for PTI v1.0 (community_event.v1).

Community events record Ubuntu-plane activity (credentials, endorsements, network connections, employment verification, programme milestones). They are not partner Trust Events (trust_event.v1). Producers MUST NOT mix community envelopes into connector TrustEvent timelines.

Normative language

The key words MUST: MUST NOT: REQUIRED: SHALL: SHALL NOT: SHOULD: SHOULD NOT: RECOMMENDED: MAY: and OPTIONAL are to be interpreted as described in RFC 2119.

Event envelope

All community events MUST conform to the envelope below regardless of ingest channel (api, console, system, seed).

{
"schema_version": "community_event.v1",
"event_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"idempotency_key": "seed:wirepick:badge:42:community.credential.verified",
"event_type": "community.credential.verified",
"context_id": "lending",
"context_ids": ["lending", "employment"],
"affected_contexts": ["lending", "employment"],
"pti_id": "pti_JANEBRW1",
"producer_id": "seed:wirepick",
"actor_user_id": 1001,
"subject_user_id": 1002,
"occurred_at": "2026-08-01T10:00:00Z",
"ingested_at": "2026-08-01T10:00:02Z",
"ingest_channel": "seed",
"correlation_id": "req_community_9a8b",
"title": "Employment verified",
"subtitle": "",
"payload": {
"badge_id": "42",
"badge_type": "employment"
},
"status": "materialized",
"steps_json": [],
"corrects_event_id": null,
"retracts_event_id": null
}

Required envelope fields

FieldRequirement
schema_versionMUST be community_event.v1 for this specification
event_idMUST be a UUID; server MAY accept client-supplied values
idempotency_keyMUST be unique per producer_id per logical community action
event_typeMUST be registered in the community event catalog
subject_user_idMUST identify the member subject of the activity
producer_idMUST identify the writing system or seed cohort
occurred_atMUST reflect real-world activity time, not ingest time
payloadMUST be a JSON object (type-specific keys MAY apply)

Optional / derived fields

FieldRequirement
pti_idSHOULD be resolved during process when a portable subject exists
actor_user_idMAY identify the acting user (issuer, endorser, verifier)
context_id / context_ids / affected_contextsSHOULD bind official trust-context slugs for hybrid lenses
ingest_channelMUST be one of api, console, system, seed when present
correlation_idMAY correlate request/trace identifiers
title / subtitleMAY supply display labels for attestation rails
corrects_event_id / retracts_event_idMAY link correction or retraction to a prior event
seed_tagMAY mark demo/seed cohorts for retract-and-reingest

Separation from partner TrustEvent

ConcernPartner (trust_event.v1)Community (community_event.v1)
StoreTrustEvent / pti_trust_eventCommunityTrustEvent / pti_community_trust_event
CatalogPartner event registry / connectorsCommunity event type catalog
Evolution timelineYesMUST NOT appear as operational rows
Score planePartner context 0–850Ubuntu headline 0–1000; hybrid bridge MAY emit native_user signals with community_event_id metadata

Event lifecycle

StateDescription
receivedPersisted ingest record awaiting process
processingResolve / bind / fan-out in progress
materializedCommunity effects applied; optional hybrid bridge completed or skipped
failedTerminal process failure with error_message
retractedSeed or producer withdrew the event

Idempotency

  • Writers MUST supply idempotency_key for mutating ingest.
  • Servers MUST enforce uniqueness on (producer_id, idempotency_key).
  • Duplicate keys MUST return the original event without double materialization side effects beyond safe no-ops.

Event type naming

Community types MUST use the community. namespace prefix with dot-separated segments, for example:

event_typeKind
community.credential.issuedbadge
community.credential.verifiedbadge
community.endorsement.recordedendorsement
community.connection.formedconnection
community.verification.employmentverification
community.programme.milestoneprogramme

Async processing

After accept, implementations SHOULD process asynchronously. Write paths that must not break UX SHOULD use a safe ingest wrapper that swallows unexpected errors after best-effort persist.