1. guides
temper
  • Temper documentation
  • 2026-07-06-cogmap-telos-differentiation
  • handoffs
  • plans
    • archived
    • evidence
  • reviews
  • specs
  • spikes
  • agents
  • auth
    • Temper auth & security
    • The authorization seam (`temper-services::auth`)
    • Cognitive-map & resource authoring authorization
    • JWT verification
    • The issuer / resource-server boundary & the machine-token contract
    • The internal reconcile channel
  • code-reviews
  • cognitive-maps
  • decisions
  • development
  • guides
    • Building a cognitive map from a large corpus
    • Using temper from Claude Desktop (and claude.ai)
    • Cloud Agent Development Guide
    • Ingesting a corpus into a context
    • Development setup
    • Drain operator queries (TraceQL)
    • Enterprise Install — Ground Up
    • Operator guide: read-only GitHub credential via a BYO App + Vercel Connect
    • Operator guide: provisioning a GitHub connection in temper
    • Installing Temper
    • Delivering L0 Kernel Cogmap Content
    • Machine Credentials
    • OpenTelemetry Setup
    • Operational Memory
    • Bootstrapping a Temper org
    • Releasing Temper
    • Self-Hosting Temper with Okta
    • Self-Hosting Temper with a SAML IdP
    • Self-Hosting Temper
    • The Slack Integration — identity, credentials, and what revocation actually means
    • Operator guide: `@temper` on Slack — end-to-end setup
    • Bootstrapping a team's self-cognition cognitive map
    • Working with Teams
    • Integrating Ruby with temper-rb
    • Deploying an Eve agent to Vercel (the steward and the citation auditor)
    • WS6 Collapsed-Schema Dev Environment
  • research
  • security
  • specs
  • doors
    • Building against Temper
    • Running Temper
    • Using Temper
  • Temper /api/query — the compositional read surface
    • Run a declared composition of situated acts.
    • Schemas
      • Composition
      • OutcomeDeclaration
      • ReturnSpec
      • Intention
      • StageNode
      • ActInvocation
      • CombineNode
      • StageInput
      • StageRelation
      • Disclosure
      • QueryResponse
      • StageResult
      • StageOutput
      • ScoreKind
      • Scoring
      • ResourceHit
      • CompositionTrace
      • StageTrace
      • InputSource
      • NarrowedBy
      • StageName
      • ActName
      • IdKind
      • IdSet
      • BoundTerm
      • Extent
      • StageDisposition
      • ActRefusal
      • PlanRefusal
      • RefusalReason
      • ActQuantity
      • QuantityScale
      • ResourceFilter
      • EdgeFilter
      • PropertyPredicate
      • PropertyOp
      • ResourceSection
      • EdgeKind
      • OrdOp
      • CogmapId
      • ContextId
      • IdProvenance
      • FacetPredicate
      • CombineOp
      • BlockId
      • MatchLocation
      • BodyStorage
      • ResourceId
      • IngestState
      • ManagedMeta
      • ProfileId
      • ResourceView
      • Polarity
      • ViaEntry
      • LensId
      • RegionId
      • CogmapRegionRow
      • RegionHit
      • StageInputTrace
      • Standing
      • ActorAuthority
      • Refusal
      • SystemAccessDetails
      • PlanRefusalDetails
      • ErrorDetails
      • ErrorDetail
      • ErrorBody
  • Temper Cloud API
    • Access
      • POST /api/access/requests — submit a join request for the gating team.
      • GET /api/access/requests/me — check own join request status.
      • DELETE /api/access/requests/me — withdraw a pending join request.
      • POST /api/access/reviews — a revoked principal asks an admin to reconsider (spec D15).
      • GET /api/access/settings — read public system settings.
    • Slack Link
      • Disconnect any principal. Operator path — offboarding and stuck users.
      • Disconnect EVERY Slack principal bound to the caller's own profile.
    • Auditor
      • auditor_dispatch
      • auditor_sweep
      • complete_auditor_job
    • Graph
      • POST /api/cogmaps/{id}/graph/slice — R4 cogmap-scoped neighborhood slice.
      • GET /api/graph/cogmaps/{id}/panorama — enter-a-cogmap Tier-0 interior.
      • GET /api/graph/contexts/composition — Beat E Tier-1: the force-graph composition of a container's (or a residual bucket's) members.
      • GET /api/graph/contexts/panorama — Beat E Tier-0: goal-container territories + residual tray.
      • GET /api/graph/home — the you→teams→cogmaps membership home.
      • GET /api/graph/regions/composition — Beat D region→resources composition drill.
    • Cognitive Maps
      • list_cognitive_maps
      • genesis
      • get_cognitive_map
      • reconcile
      • analytics
      • grant_cogmap_access
      • revoke_cogmap_access
      • materialize
      • materialize_delta
      • region_metrics
      • shape
      • bind_team
      • unbind_team
    • Contexts
      • list_contexts
      • create_context
      • get_context
      • context_materialize
      • reassign
      • context_region_metrics
      • rename
      • context_shape
      • share_team
      • unshare_team
    • Events
      • cursor
      • GET /api/graph/elements/{kind}/{id}/trail — R5 element event-trail. kind ∈ {node, edge}.
    • Facets
      • set_facet
      • Read the live facets of one edge.
      • Set a facet whose owner is an **edge** rather than a resource.
      • Read the live facets of one resource — the confirming read for a write that steers region formation and Atlas grouping.
    • Health
      • health_check
    • Ingest
      • create_ingest
      • update_ingest
      • list_blocks
      • append_block
      • finalize_resource
    • Invitations
      • accept
      • decline
      • list_mine
      • list_team_invitations
      • revoke_team_invitation
      • create_team_invitation
    • Invocations
      • list_invocations
      • open
      • show
      • close
    • Profile
      • get_profile
      • update_profile
      • list_auth_links
    • Query
      • `POST /api/query`.
    • Relationships
      • assert
      • fold
      • retype
      • reweight
    • Resources
      • `GET /api/resources` — **one response type, unconditionally.**
      • create_resource
      • get_resource
      • delete_resource
      • update_resource
      • List the finding at `{id}`'s citation-audit trail — one row per audit, each naming its auditor.
      • Record an auditor's signed defensibility verdict on one `(block, source)` citation of the finding at `{id}`. CONFORM to `handlers::edges::assert` (the sibling authored-write handler): thin — build the command, dispatch it, map the error. No persistence he
      • get_content
      • list_resource_edges
      • resource_evidence
      • grant_resource_access
      • revoke_resource_access
      • resource_lineage
      • provenance
      • annotate_resource
    • Meta
      • get_meta
      • update_meta
    • Reassign
      • reassign_resource
      • reassign_team
    • Search
      • `POST /api/search`.
    • Steward
      • candidates
      • dispatch
      • sweep
      • delta
      • advance
    • Teams
      • list_teams
      • create_team
      • detail
      • delete_team
      • update_team
      • add_member
      • remove_member
      • change_role
    • Schemas
      • AcceptInvitationResponse
      • ActInput
      • ActInvocation
      • ActName
      • ActQuantity
      • ActRefusal
      • ActorAuthority
      • AddMemberRequest
      • AdvanceWatermarkAck
      • AdvanceWatermarkRequest
      • AgentAuthorship
      • AppendBlockPayload
      • AssertRelationshipRequest
      • AtlasEdge
      • AtlasHome
      • AtlasNode
      • AtlasSubgraph
      • AuditCitation
      • AuditSweepRow
      • AuditorDispatchTickRequest
      • AuditorDispatchTickResponse
      • AuditorJobCompleteAck
      • BindTeamOutcome
      • BindTeamRequest
      • BlockId
      • BlockProvenanceRow
      • BlocksResponse
      • BodyStorage
      • Bridge
      • BulkReassignAck
      • BulkReassignRequest
      • ChangeRoleRequest
      • CharterBlock
      • CharterDisposition
      • CitationAuditRequest
      • CitationAuditRow
      • ClaimedAuditJob
      • ClaimedJob
      • CloseInvocationRequest
      • CogmapAnalyticsRow
      • CogmapDetail
      • CogmapFoundationRow
      • CogmapGrantBody
      • CogmapId
      • CogmapRegionMetricsRow
      • CogmapRegionRow
      • CogmapRegulationRow
      • CogmapRevokeBody
      • CogmapRow
      • CogmapStaleness
      • CombineNode
      • CombineOp
      • Composition
      • CompositionTrace
      • ConfidenceBand
      • ContentResponse
      • ContextCreateRequest
      • ContextId
      • ContextOwnerRef
      • ContextPanorama
      • ContextRow
      • ContextRowWithCounts
      • CorrelationId
      • CreateCogmapOutcome
      • CreateCogmapRequest
      • CreateInvitationRequest
      • CreateRequestBody
      • CreateReviewBody
      • DeleteResponse
      • DeviceOverrides
      • DispatchTickRequest
      • DispatchTickResponse
      • Disposition
      • DriftSweepRow
      • EdgeFacetRow
      • EdgeFacetSetRequest
      • EdgeFacetsResponse
      • EdgeFilter
      • EdgeId
      • EdgeKind
      • ElementEvent
      • ElementKind
      • EmbedDispatchSummary
      • Entitlements
      • ErrorBody
      • ErrorDetail
      • ErrorDetails
      • EventCursorResponse
      • EventTrail
      • ExactArm
      • ExactHit
      • Extent
      • FacetAck
      • FacetPredicate
      • FacetSetRequest
      • FinalizePayload
      • FoldRelationshipRequest
      • GrantOutcome
      • GraphEdgeRow
      • GroupKeyMeta
      • HealthResponse
      • HomeCogmap
      • HomeContext
      • IdKind
      • IdProvenance
      • IdSet
      • IdpRevocation
      • IngestCreateResponse
      • IngestDelta
      • IngestPayload
      • IngestState
      • InheritedReadGrant
      • InheritedShare
      • InputSource
      • Intention
      • InvitationStatus
      • InvitationTokenRequest
      • InviteeInvitation
      • InvocationAck
      • InvocationActRow
      • InvocationCloseAck
      • InvocationId
      • InvocationSummary
      • InvocationView
      • JoinRequest
      • JoinRequestStatus
      • LensId
      • LineageNode
      • ManagedMeta
      • MatchLocation
      • MaterializeAck
      • MaterializeDelta
      • MaterializeRequest
      • MergePolicy
      • MetaUpdatePayload
      • NarrowedBy
      • NodeHome
      • OpenInvocationRequest
      • OrdOp
      • OrphanNode
      • OutcomeDeclaration
      • PlanRefusal
      • PlanRefusalDetails
      • Polarity
      • Profile
      • ProfileAuthLink
      • ProfileId
      • ProfileUpdateRequest
      • ProfileWithEntitlements
      • PropertyOp
      • PropertyPredicate
      • ProvenanceSource
      • PublicSystemSettings
      • QuantityScale
      • QueryResponse
      • ReassignAck
      • ReassignContextOutcome
      • ReassignContextRequest
      • ReassignResourceRequest
      • ReconcileCogmapRequest
      • ReconcileEdge
      • ReconcileEdgeTombstone
      • ReconcileEntry
      • ReconcileOutcome
      • ReconcileTelos
      • ReconcileTelosBlock
      • ReconcileTombstone
      • Refusal
      • RefusalReason
      • RegionHit
      • RegionId
      • RelationshipAck
      • RemoveMemberOutcome
      • RenameContextOutcome
      • RenameContextRequest
      • ResidualBucket
      • ResidualContext
      • ResidualGroups
      • ResidualOwnedReach
      • ResourceAnnotateRequest
      • ResourceCreateRequest
      • ResourceFacetRow
      • ResourceFacets
      • ResourceFacetsResponse
      • ResourceFilter
      • ResourceGrantBody
      • ResourceHit
      • ResourceId
      • ResourceLineage
      • ResourceListResponse
      • ResourceRevokeBody
      • ResourceSection
      • ResourceSortField
      • ResourceUpdateRequest
      • ResourceView
      • ReturnSpec
      • RetypeRelationshipRequest
      • RevokeOutcome
      • ReweightRelationshipRequest
      • ScoreKind
      • Scoring
      • SearchParams
      • SearchReason
      • SearchResponse
      • SearchResultRow
      • SearchScope
      • SearchScopeInfo
      • SegmentInfo
      • SegmentedBegin
      • SegmentedBeginResponse
      • ShareContextOutcome
      • ShareContextRequest
      • SlackDisconnectRequest
      • SlackDisconnectResponse
      • SlackDisconnectedPrincipal
      • SliceRequest
      • SortOrder
      • StageDisposition
      • StageInput
      • StageInputTrace
      • StageName
      • StageNode
      • StageOutput
      • StageRelation
      • StageResult
      • StageTrace
      • Standing
      • StandingShape
      • Subscription
      • SubscriptionOverride
      • SystemAccessDetails
      • TeamCreateRequest
      • TeamDetail
      • TeamInvitation
      • TeamMemberDetail
      • TeamMemberRow
      • TeamMemberSource
      • TeamRole
      • TeamRow
      • TeamUpdateRequest
      • Territory
      • TerritoryKind
      • TerritoryOverview
      • UnbindTeamOutcome
      • UnshareContextOutcome
      • VaultConfig
      • ViaEntry
      • WideArm
      • WideHit
  1. guides

Operator guide: provisioning a GitHub connection in temper

This is the companion to github-connection-infra.md. That guide
sets up the infra (the GitHub App, the Vercel Connect connector, the broker env vars). This guide
picks up where it leaves off: provisioning the temper connection row, attaching the credential,
declaring the webhook events and tool manifest, and reading the drift check output.
All commands use the temper admin connection CLI suite. Every step has a verification — do not
skip them.
Prerequisite. The infra guide is complete: the GitHub App exists with read-only permissions,
the non-managed connector exists on Vercel Connect, the App is installed on your repos, and the
broker env vars are set on the temper-api project and redeployed. Without the broker, the drift
check at attach-credential returns verified: false.

The four commands#

StepCommandWhat it does
1temper admin connection provisionCreates the kb_connections row + profile + emitter entity + home context. Born needs_credential.
2temper admin connection attach-credentialAttaches the credential reference. Runs the drift check — mints once, reads metadata.permissions, compares against declared reach.
3temper admin connection set-webhooksRegisters the remote event types. Non-empty ⇒ ledger-capable — events land.
4temper admin connection set-toolsDeclares the read-only remote tools. Non-empty ⇒ reach-capable — agents can read the remote back.
After step 2, the connection is verified. After step 3, events can land. After step 4, agents can
reach the remote. Steps 3 and 4 can be done in either order, but both must be done for the connection
to be useful.

Step 1 — provision the connection row#

Arguments:
ArgWhat it isExample
--providerThe remote systemgithub
--nameHuman-facing name; the addressable slug is derived from itgithub-readonly
--owner-teamTeam recorded as the connection's OWNER (not its reach). Omitting means teamless, which is admin-only and fails closedtemper-system
--reachThe grain the credential is scoped at, in the provider's terms: org | workspace | installation | repo-set | projectorg
--coversWhat the credential can ACTUALLY see, in provider termstasker-systems
Declaring reach is not overhead — it IS the declaration. A connector is a reach declaration.
You cannot have 50 teams with 50 distinct reaches and fewer than 50 declarations. The
--reach/--covers values are where the honesty lives; the drift check at attach compares them
against what the provider actually returns.
Finding your team slug:
Verify — the response includes:
{
  "id": "<uuid>",
  "slug": "github-readonly",
  "credential": null,
  "webhook_events": [],
  "tool_manifest": {},
  "reach_granularity": "org",
  "reach_covers": "tasker-systems"
}
The trailing line says: needs_credential — no credential is attached. That is correct — step 2
fixes it.
Copy the id — it's the <ID> argument for the next commands.

Step 2 — attach the credential (the drift check runs here)#

Arguments:
ArgWhat it isExample
--brokerThe implementation behind the broker seam. Never a connector idvercel-connect
--connectorThe broker's identifier for this connectorgithub/tasker-systems-temper-readonly
--installationThe GitHub App installation ID (from the install URL)154768494
<ID> (positional)The connection ID from step 101a016db-...
No secret is stored. --broker names the implementation; --connector identifies a connector
that the broker holds the secret for. The connector id lives on the row, per instance — which is
what lets a self-hosted operator use their own connectors.
Verify — the response includes a verification object:
{
  "verification": {
    "verified": true,
    "observed_reach": {
      "permissions": {
        "contents": "read",
        "metadata": "read",
        "pull_requests": "read"
      },
      "repository_selection": "all"
    }
  }
}
This is the drift check — read it carefully. The mint returned metadata.permissions and
metadata.repository_selection from the provider, and the service compared them against the declared
reach_granularity/reach_covers.
What each outcome means:
verifiedobserved_reachMeaning
trueread scopes onlyThe App is read-only, the token is read-only, the drift check passed.
truewrite scopesThe App has write permissions — the token is NOT read-only. Go back to the infra guide and fix the App.
false"note": "not verified — no credential broker is configured"The broker env vars are missing on the temper-api project, or it wasn't redeployed. See infra guide Step 4.
false"note": "needs consent"The App isn't installed on any repos, or the installation ID is wrong. See infra guide Step 3.
The trailing line names any gap between declared and observed reach:
Where the actual reach exceeds the declared, that gap is real and must be acknowledged before
granting a team.
That gap is the excess-reach affirmation (B3) — it's working as designed. When you grant a team reach
on this connection, the grant-reach command will require an --affirm-reach rationale if the
declared reach is broad.

Step 3 — register webhook events (ledger-capable)#

--event is repeatable. The event names are the provider's own (e.g. pull_request,
issue_comment, push).
Replaces wholesale. set-webhooks mirrors what the remote is actually configured to send —
it does not merge. A merge would let a stale entry outlive the webhook it names.
Verify:
{
  "webhook_events": ["pull_request"]
}
The trailing line no longer says "Not ledger-capable" — the connection now accepts events.

Step 4 — declare the tool manifest (reach-capable)#

--tool is repeatable. The tool names are the read-only remote tools an agent can call via the
brokered token.
The manifest is not decorative. It is the evidence the provider is admissible at all. An empty
manifest means judgment is IMPOSSIBLE, not merely unconfigured. A subscription against a
reach-incapable connection is legal and durable, but inert for judgment.
Verify:
{
  "tool_manifest": [
    "github_get_file_contents",
    "github_get_pull_request_files",
    ...
  ]
}
The trailing line no longer says "Not reach-capable" — agents can now read the remote back.

Step 5 — grant a team reach (optional, separate from ownership)#

Owning a connection is NOT reaching it. A team must be granted read-reach for its members to inherit
read on what the connection receives.
When --affirm-reach is required: when the connection declares_reach() (i.e.
reach_granularity or reach_covers is set) AND the observed reach is broad. The rationale is a
named human's acknowledgment that the team's temper scope is comparably broad — it is recorded, not
just accepted.
What happens without it: if the connection declares reach and no affirmation is provided, the
grant is rejected with 409 Conflict. If the connection declares no reach, the grant is a plain
grant with no affirmation needed.
Verify:
The reach_affirmed_by / reach_affirmed_at / reach_affirmation fields are populated when an
affirmation was recorded.

The full sequence, as one reference#


Troubleshooting#

invalid connection id 'github-readonly': invalid character — the <ID> argument is a UUID,
not the slug. Use the id from the provision response.
not verified — no credential broker is configured — the VERCEL_CONNECT_* env vars are missing
on the temper-api project, or it wasn't redeployed after setting them. See the infra guide Step 4.
needs consent — the App isn't installed on any repos, or the installation ID is wrong. Re-install
at https://github.com/apps/<app-slug>/installations/new and use the installation ID from the URL.
Write scopes in observed_reach.permissions — the GitHub App has write permissions. Go back to
the infra guide Step 1, re-read the permissions, and fix the App. Re-attach the credential after
fixing; the drift check will re-run.
409 Conflict on grant-reach — the connection declares reach and you didn't provide
--affirm-reach. Add it with a rationale naming why the team's scope is comparably broad.
Modified at 2026-08-19 17:59:52
Previous
Operator guide: read-only GitHub credential via a BYO App + Vercel Connect
Next
Installing Temper
Built with