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.