knowledge API
Table of Contents
-
upsquad/knowledge/v1/corpus_integrity.proto
-
upsquad/knowledge/v1/knowledge.proto
-
upsquad/knowledge/v1/repo.proto
upsquad/knowledge/v1/corpus_integrity.proto
AdjudicateConflictRequest
AdjudicateConflictRequest is a HUMAN verdict. There is no agent id on it and there is nowhere to put one.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | The team whose queue holds the finding. Required; a member of team A cannot rule on team B's queue even with the capability. | |
| conflict_id | string | The finding to rule on, by row id. | |
| new_status | ConflictStatus | CONFIRMED, DISMISSED, FIXED or SUPERSEDED. OPEN is refused — a finding re-opens on evidence (TK-9.11), not on a verdict. | |
| note | string | Why. Recorded beside the verdict, because a verdict's reasoning is a property of the verdict and TK-9.13 feeds both back into calibration. |
AdjudicateConflictResponse
AdjudicateConflictResponse returns the finding as it now stands.
| Field | Type | Label | Description |
|---|---|---|---|
| conflict | Conflict | The finding after the verdict. |
Conflict
Conflict is one finding.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | The row id. Machines hold this; people paste the permalink. | |
| team_unit_id | string | The team whose queue owns this finding. A conflict is a fact about ONE team's corpus. | |
| permalink | string | "C-###" — stable, per team, resolving to exactly one row. A fix task, an issue or a Slack message points here. | |
| conflict_class | ConflictClass | Which of TK-9.1's five classes this finding is. | |
| status | ConflictStatus | Where the finding is in TK-9.10's lifecycle. Read WITH verdict_by: an OPEN finding that carries a verdict was re-opened after adjudication. | |
| severity | ConflictSeverity | UNKNOWN for everything the window arm raises — see the enum. | |
| summary | string | One line: what disagrees. | |
| first_seen_at | google.protobuf.Timestamp | When the finding was first raised. | |
| last_seen_at | google.protobuf.Timestamp | The most recent sighting. Beside sighting_count this is what tells a triager whether a finding is live or historical. | |
| verdict_by_member_id | string | The MEMBER who ruled, empty until a human has. Never an agent (TK-9.12). |
It is NOT cleared when a dismissal lapses and the finding re-opens: an open finding that carries a verdict is "re-opened after adjudication", which is a fact the queue needs and TK-9.13's judge calibration reads. Read status for the current state and this for the last human ruling. |
| verdict_at | google.protobuf.Timestamp | | When the human ruled. Paired with verdict_by_member_id by a CHECK: half a verdict is not a verdict. |
| verdict_note | string | | Why they ruled that way. TK-9.13 feeds verdicts AND their reasoning back into judge calibration. |
| sighting_count | int32 | | How many times this finding has been reported. Carried on the LIST row, not only in the drawer: "seen four times" is the most useful triage signal a queue row has, and a signal that needs a click is a signal most readers never see. |
| passages | ConflictPassage | repeated | Populated by GetConflict only. A list that fanned out to every passage of every row would be a fan-out on the surface people leave open. |
| sightings | ConflictSighting | repeated | Populated by GetConflict only, newest first and bounded. A conflict an agent hits every turn accumulates sightings quickly. |
ConflictPassage
ConflictPassage is one side of a conflict.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | The passage row id. | |
| doc_id | string | The DOCUMENT (identity — survives content change). | |
| version_id | string | The VERSION that was judged (content address — does not). | |
| source_doc_id | string | The version's address, which is the handle search_knowledge prints and get_document takes. One handle, everywhere. | |
| text_sha256 | string | The extraction hash AS JUDGED. Empty when the judged version had no extraction to hash, which is what makes a later stickiness comparison UNDECIDABLE for this passage. | |
| char_start | int32 | Character range within the extraction, when the producer knew one. A report names documents, not offsets, so the window arm leaves both zero; the claims sweep will not. | |
| char_end | int32 | Exclusive end of the character range. Paired with char_start by a CHECK. | |
| label | string | The document's human label, resolved on READ rather than stored: a filename changes, and a stale label inside a governance citation is a confident falsehood about which document was judged. |
ConflictSighting
ConflictSighting is one report. A second report is a sighting, not a row.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | The sighting row id. | |
| reporter_kind | ReporterKind | Which of the two reporters this was. Determines which id below is set. | |
| reporter_agent_id | string | Exactly one of the two is set, per the exclusive arc. | |
| reporter_member_id | string | Set when reporter_kind is MEMBER; empty otherwise. | |
| task_context | string | TK-9.4: what the reporter was doing when the disagreement bit them. This is the field that makes a repeat sighting EVIDENCE rather than noise. | |
| detail | string | What the reporter said was wrong, in their words. Distinct from the finding's own summary: a second reporter may name a different symptom of the same disagreement, and flattening the two loses that. | |
| stickiness | Stickiness | What TK-9.11's comparison measured for THIS sighting. | |
| seen_at | google.protobuf.Timestamp | When this report arrived. |
GetConflictRequest
GetConflictRequest resolves one finding.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | The team whose queue to read. Required; it is the gate. | |
| ref | string | A row id OR a C-### permalink. One field, because the permalink is what people paste and the id is what machines hold, and a second field would be a second thing that can be wrong. |
GetConflictResponse
GetConflictResponse carries the finding with its passages and sightings.
| Field | Type | Label | Description |
|---|---|---|---|
| conflict | Conflict | The finding, with passages and sightings populated. |
ListConflictsRequest
ListConflictsRequest pages one team's queue.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | The team whose queue to read. Required; it is the gate, not a filter. | |
| statuses | ConflictStatus | repeated | Empty means the DEFAULT view, which excludes dismissed. It does not mean "everything". |
| page_size | int32 | Bounded server-side. Zero selects the default. | |
| offset | int32 | Rows to skip. Negative is treated as zero. |
ListConflictsResponse
ListConflictsResponse is one page plus the facts an empty page needs.
| Field | Type | Label | Description |
|---|---|---|---|
| conflicts | Conflict | repeated | The page, newest sighting first. |
| summary | QueueSummary | ALWAYS populated, including when conflicts is non-empty. An empty list has four different meanings and a console that must issue a second RPC to learn which will render the wrong one. |
QueueAggregateBucket
QueueAggregateBucket counts one class/status pair in the full current queue.
| Field | Type | Label | Description |
|---|---|---|---|
| conflict_class | ConflictClass | The finding taxonomy, never UNSPECIFIED. | |
| status | ConflictStatus | The current lifecycle state, never UNSPECIFIED. | |
| count | int64 | Number of deduplicated findings in this bucket; zero is measured. |
QueueAggregates
QueueAggregates measures current human queue completion, NOT detector precision or historical judgement throughput. Findings are deduplicated rows, never sightings or passages. Machine funnel stages remain in SweepStatus.
| Field | Type | Label | Description |
|---|---|---|---|
| buckets | QueueAggregateBucket | repeated | All five classes crossed with all five lifecycle states, including zero buckets, in enum order. Each finding belongs to exactly one bucket. |
| surfaced_count | int64 | All findings currently in the team's queue, including dismissed. | |
| human_judged_count | int64 | Currently confirmed, fixed, superseded or dismissed. A reopened finding is open and no longer belongs to this numerator, even with an old verdict. | |
| human_judged_rate | double | optional | Server-computed human_judged_count / surfaced_count, a fraction in [0,1]. Absent when surfaced_count is zero: no denominator, not 0% or 100%. |
QueueSummary
QueueSummary is the tab badge and the "25 of 91" denominator.
| Field | Type | Label | Description |
|---|---|---|---|
| open_count | int32 | The badge number: findings awaiting a human. open only — a confirmed finding already has its verdict and is somebody's task, and badging it would make the badge un-clearable. | |
| total_in_view | int32 | How many rows the current filter matches, so a page can say "25 of 91" rather than implying 25 is all there is. NOT the page length. | |
| sweep | SweepStatus | Where the team's detection stands. Always populated — see ListConflictsResponse.summary. | |
| aggregates | QueueAggregates | Current human queue completion, across ALL findings for this org/team, including dismissed, independent of status filters and pagination. Absent on older servers; absence does not mean an empty measured queue. |
ReportConflictRequest
ReportConflictRequest is one in-context human report. The agent tool's equivalent arrives through the MCP server and lands on the same store primitive, which is what makes the two dedupe onto one finding.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | The team whose queue receives the finding. Required. | |
| conflict_class | ConflictClass | Which class the reporter says this is. Not re-classified by the server: re-classifying a report is a judgement, and this arm makes none. | |
| summary | string | One line: what disagrees. Required — a queue entry that cannot say what it found cannot be triaged. | |
| source_doc_ids | string | repeated | The documents the reporter says disagree, as the source_doc_id handles search_knowledge prints. Required; doc_doc needs at least two. |
Every one must be visible to the caller's effective knowledge-source set. A partially-resolvable report is REFUSED, not silently narrowed: a report of "A and B contradict" that becomes a finding about A alone says something the reporter did not say. | | task_context | string | | TK-9.4: what the reporter was doing. | | detail | string | | What the reporter says is wrong, in their words. |
ReportConflictResponse
ReportConflictResponse says WHICH finding received the report and what happened to it, so the caller can render the mockup's sentence.
| Field | Type | Label | Description |
|---|---|---|---|
| conflict | Conflict | The finding the report landed on — created or matched. | |
| created | bool | False when the report DEDUPED onto an existing finding. The mockup's wire behaviour — "matched existing C-108, your context attached" — needs this and stickiness to be sayable at all. | |
| stickiness | Stickiness | What TK-9.11's comparison measured for this report. | |
| reopened | bool | Set when a dismissal LAPSED and this report re-opened the finding. | |
| undecidable_passages | string | repeated | The labels of the passages whose hash could NOT be compared, when stickiness is STICKINESS_UNDECIDABLE. Named rather than counted: an operator asked to look at a corpus artefact needs to know which one. |
| sighting_count | int32 | The count AFTER this report. Two sightings on one conflict is the shape acceptance 8 asks for, and this is where it is visible. |
SweepStatus
SweepStatus is everything H4's empty state is computed from.
| Field | Type | Label | Description |
|---|---|---|---|
| configured | bool | Whether conflict detection is switched on for the team. False for every team in Phase 1 — the sweep is Phase 2+. | |
| last_run_at | google.protobuf.Timestamp | The last sweep ATTEMPT, successful or not. | |
| last_success_at | google.protobuf.Timestamp | The last sweep that COMPLETED. The distinction is the whole of state 4: a detector that runs nightly and fails nightly has a recent last_run_at and a stale last_success_at, and reporting the first would be a freshness claim about a failure. | |
| pairs_checked | int64 | TK-9.7's first funnel stage from the last successful sweep. "0 conflicts" alone is not a report; "0 conflicts, checked 1,204 pairs" is. | |
| reason | string | Why there is no recent success. H4's rule is "the last successful sweep time, OR THE REASON there is none". | |
| state | QueueState | The computed state, so the console cannot derive a fifth one. | |
| rendered | string | The server's own rendering of the state. Carried on the wire for the same reason RepoMap carries its staleness marker: the console, the CLI and any digest must not be able to describe the same state differently. |
ConflictClass
ConflictClass is TK-9.1's five first-class classes.
All five are on the wire although the window arm produces only the first three. A queue that cannot REPRESENT a class cannot receive it when its detector lands without a migration over live governance rows, and detectors (v) and (vi) are Phase 2+.
| Name | Number | Description |
|---|---|---|
| CONFLICT_CLASS_UNSPECIFIED | 0 | Never sent by this service. Present because proto3 requires a zero value; a request carrying it is refused rather than defaulted to a class. |
| CONFLICT_CLASS_DOC_DOC | 1 | Two documents contradict each other. |
| CONFLICT_CLASS_INTRA_DOC | 2 | One document contradicts itself. |
| CONFLICT_CLASS_DOC_CODE | 3 | A document has drifted from the code it describes. |
| CONFLICT_CLASS_DUPLICATION | 4 | Duplicated content with no single owner. Detector (v), Phase 2+. |
| CONFLICT_CLASS_AMBIGUITY | 5 | A term used to mean different things. Detector (vi), Phase 2+ and LAST (TK-9.9) — it ships into a queue that has already demonstrated precision, or not at all. |
ConflictSeverity
ConflictSeverity drives the queue's severity chip. Colour is reserved for it; the taxonomy chips are neutral (HLD §11.7).
| Name | Number | Description |
|---|---|---|
| CONFLICT_SEVERITY_UNSPECIFIED | 0 | Never sent by this service; UNKNOWN is the honest "not judged" value and it is a value, not an absence. |
| CONFLICT_SEVERITY_UNKNOWN | 1 | What the window arm writes. A report says "these disagree"; nothing in this arm judges HOW BADLY, and inventing a severity would be a number with no measurement behind it. |
| CONFLICT_SEVERITY_LOW | 2 | Set by a human adjudicating, or by a Phase-2 detector that measured it. |
| CONFLICT_SEVERITY_MEDIUM | 3 | Set by a human adjudicating, or by a Phase-2 detector that measured it. |
| CONFLICT_SEVERITY_HIGH | 4 | Set by a human adjudicating, or by a Phase-2 detector that measured it. |
ConflictStatus
ConflictStatus is TK-9.10's lifecycle.
| Name | Number | Description |
|---|---|---|
| CONFLICT_STATUS_UNSPECIFIED | 0 | Never sent by this service. A status the server could not name is a bug, not a state, and defaulting it to OPEN would invent a finding. |
| CONFLICT_STATUS_OPEN | 1 | Raised and awaiting a human. The ONLY status a write path can create, and the only one answer-time surfacing reads. |
| CONFLICT_STATUS_CONFIRMED | 2 | Requires a human verdict (TK-9.12). |
| CONFLICT_STATUS_FIXED | 3 | The confirmed finding has been repaired. Reachable only from CONFIRMED: retiring a finding nobody ruled on would be TK-9.12 by the back door. |
| CONFLICT_STATUS_DISMISSED | 4 | Requires a human verdict (TK-9.12), and is STICKY until a judged passage changes (TK-9.11). |
| CONFLICT_STATUS_SUPERSEDED | 5 | A human decided which side wins. NG-10: the losing document is NOT edited. |
QueueState
QueueState is H4's four empty states. None may render identically to another — that is the whole content of UX acceptance 2.
| Name | Number | Description |
|---|---|---|
| QUEUE_STATE_UNSPECIFIED | 0 | Never sent. A queue state the server could not establish renders as itself rather than as the nearest familiar sentence — see SweepStatus.rendered. |
| QUEUE_STATE_NOT_CONFIGURED | 1 | No sweep configured. THE DAY-0 WINDOW STATE, and every team's state throughout Phase 1. |
| QUEUE_STATE_NEVER_RUN | 2 | Configured, never run — the dead-detector case. |
| QUEUE_STATE_CLEAN | 3 | Ran, clean. |
| QUEUE_STATE_STALE | 4 | Ran, but the last success is stale or there has never been one. Carries the reason. |
ReporterKind
ReporterKind is the sighting's exclusive arc. Agent evidence and human evidence are different signals: "three agents hit this mid-task" and "a curator noticed it" say different things about a finding.
| Name | Number | Description |
|---|---|---|
| REPORTER_KIND_UNSPECIFIED | 0 | Never stored: the exclusive-arc CHECK on conflict_sightings refuses a sighting whose reporter kind is not one of the two below. |
| REPORTER_KIND_AGENT | 1 | Reported by an agent through the report_knowledge_issue MCP tool, mid-task. |
| REPORTER_KIND_MEMBER | 2 | Reported by a person through the in-context report on the doc viewer or the answer surface (TK-9.4's primary entry; the console button is the fallback). |
Stickiness
Stickiness is what TK-9.11's hash comparison measured for one sighting.
| Name | Number | Description |
|---|---|---|
| STICKINESS_UNSPECIFIED | 0 | Never stored. Every sighting records which of the four the writer measured, because an unrecorded comparison is a verdict nobody can audit. |
| STICKINESS_NOT_DISMISSED | 1 | The finding was not dismissed, so stickiness did not apply. Distinct from HELD: "the verdict held" and "there was no verdict" are different facts. |
| STICKINESS_HELD | 2 | Dismissed, and every recorded hash still matches. The dismissal SURVIVES a re-sync — without this arm the queue forgets its own verdicts. |
| STICKINESS_LAPSED | 3 | Dismissed, and at least one judged passage CHANGED. The dismissal lapses and the finding re-opens — without this arm the queue nags. |
| STICKINESS_UNDECIDABLE | 4 | Dismissed, nothing demonstrably changed, but at least one passage could not be compared. The dismissal is HELD and the unverifiability is reported. |
CorpusIntegrityService
CorpusIntegrityService is the management surface for a team's corpus-integrity queue. Every operation is tenant-scoped: the owning org and the acting member come from the request scope, never from the request body, and every statement carries an explicit org predicate on top of row-level security.
Authorization (handler_perms.go):
- reads (ListConflicts, GetConflict) — knowledge.read
- report (ReportConflict) — knowledge.read, deliberately: reporting is reading with a complaint attached, and requiring knowledge.manage would mean only curators can flag a contradiction — which defeats TK-9.4's "primary entry is the doc-viewer / answer surface".
- verdict (AdjudicateConflict) — knowledge.manage, and a HUMAN.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| ReportConflict | ReportConflictRequest | ReportConflictResponse | ReportConflict records a reported disagreement. |
It DEDUPES: a report whose (class, document set) matches an existing finding becomes an additional SIGHTING on that finding, carrying the task context it was reported from. A second sighting is evidence, not a duplicate row (TK-9.4).
This is the same store primitive the report_knowledge_issue MCP tool calls, which is what makes "the agent tool and the in-context human report dedupe into ONE conflict with TWO sightings" a property of one implementation rather than an agreement between two. |
| ListConflicts | ListConflictsRequest | ListConflictsResponse | ListConflicts pages a team's queue.
The DEFAULT view excludes dismissed (HLD §11.7). An empty statuses means that default, NOT "everything": a queue whose depth never drops because it shows its own dismissals is a queue people stop reading. |
| GetConflict | GetConflictRequest | GetConflictResponse | GetConflict resolves ONE finding by row id or by C-### permalink, with its passages and its sightings. |
| AdjudicateConflict | AdjudicateConflictRequest | AdjudicateConflictResponse | AdjudicateConflict records a HUMAN verdict (TK-9.12). It is the only way into confirmed or dismissed, and fixed / superseded are reachable only from confirmed — both are statements about a finding a human already accepted.
It cannot set open: a conflict re-opens when a judged passage CHANGES (TK-9.11), which is evidence, not a click. |
upsquad/knowledge/v1/document.proto
ByteRange
ByteRange is a bounded window over the SERVED REPRESENTATION, in bytes.
Bytes and not runes: "byte-faithful" is the property being delivered, and a rune-indexed window over a PDF or a docx is not a window over anything the caller can address.
A RANGE IS NOT A WAY AROUND THE SIZE CEILING, and that is worth stating because the truncation notice on every other response invites paging. The stored hash is over the WHOLE artefact, so verification runs over the whole artefact before any window is taken: an artefact above the server's verification ceiling is refused outright (FAILED_PRECONDITION naming the size and the limit) and no offset can reach it.
| Field | Type | Label | Description |
|---|---|---|---|
| offset | int64 | offset is the first byte to serve, 0-based. An offset past the end of the representation is InvalidArgument, not an empty success. | |
| length | int64 | length is how many bytes to serve. 0 means "to the end", subject to the budget in max_bytes. |
DocumentProvenance
DocumentProvenance is everything a reader needs to say WHERE this came from and WHEN — PRD TK-2.3's "source, external id, filename, modified_at, content_hash, ingestion time", plus the fields HLD §4.3 added to make the integrity check falsifiable.
| Field | Type | Label | Description |
|---|---|---|---|
| doc_id | string | doc_id is the registry row: the DOCUMENT, whose identity is (source_id, external_id) and which survives every content change. | |
| version_id | string | version_id is the knowledge_doc_versions row that was served. | |
| source_id | string | source_id is the knowledge_sources row the document belongs to. | |
| source_doc_id | string | source_doc_id is the VERSION ADDRESS — the value rag_chunks already carries and the handle search results print. | |
| external_id | string | external_id is the upstream stable id. A backfilled legacy row carries "legacy:<source_doc_id>" and is flagged for re-sync (LLD §3.5). | |
| source_name | string | source_name is the human-readable corpus name. Best-effort: a soft-deleted source still has readable content, so an empty value is a missing LABEL and never a gate. | |
| filename | string | filename is the document's file name, where the producer recorded one. | |
| title | string | title is the document's title, where the producer recorded one. | |
| path | string | path is the document's upstream path, where the producer recorded one. | |
| modified_at | google.protobuf.Timestamp | modified_at is the upstream modification time, where one was captured. | |
| raw_sha256 | string | raw_sha256 is the hash of the original bytes. EMPTY means "never recorded", which is reachable only for artefact_state='raw_unavailable' rows; it is not flattened to a sentinel, because an empty hash that reads as populated is exactly what migration 228's CHECKs exist to prevent. | |
| text_sha256 | string | text_sha256 is the hash of the persisted extraction. Empty when there is no extraction to hash. | |
| extractor_version | string | extractor_version dates text_sha256. Without it a text_sha256 mismatch cannot be told apart from corruption: a mismatch at the SAME version is corruption, a mismatch ACROSS versions is a re-extraction event (HLD §4.3, A2-b). | |
| content_type | string | content_type is the document's media type as recorded at ingest. | |
| size_bytes | int64 | size_bytes is the size of the RAW document as recorded at ingest, which is not in general the size of the representation served — see Truncation.total_bytes for that. | |
| ingested_at | google.protobuf.Timestamp | ingested_at is when this version was persisted. It is the timestamp behind the "as of the last sync" phrasing claim bound C3 requires. | |
| artefact_state | string | artefact_state is what the registry knows about this version's bytes: 'present' or 'raw_unavailable' from knowledge_doc_versions, or 'unregistered' for a document that has no registry row at all — the whole corpus ingested before the persistence path existed, until the backfill gives each one a row. It is the DISCRIMINATOR for the empty hash/type/size fields above, not a label. 'unregistered' is a WIRE value only; the database CHECK admits the other two, because a row saying "there is no row" would be a contradiction someone could persist. | |
| doc_kind | string | doc_kind is 'document' | |
| content_provenance | ContentProvenance | content_provenance says whether the served bytes are the persisted artefact or a reconstruction from chunks. | |
| currency_detail | string | currency_detail renders the currency marker in words, including the ingest timestamp behind "as of the last sync" (claim bound C3). | |
| deleted_at | google.protobuf.Timestamp | deleted_at is set when the registry row is soft-deleted. It is carried SEPARATELY from currency on purpose: a document deleted HERE and a document deleted UPSTREAM are different facts, and folding the first into CURRENCY_GONE_UPSTREAM would assert an upstream observation we have not made. |
GetDocumentRequest
GetDocumentRequest addresses ONE document version.
| Field | Type | Label | Description |
|---|---|---|---|
| doc_ref | string | doc_ref is either a source_doc_id (a VERSION address — the handle every search hit prints) or a knowledge_docs id (a DOCUMENT identity, resolved to its current version). Both are UUIDs and the server tries them in that order; a value that is neither is answered with the SAME not-found as a document belonging to another team, because a caller able to tell those apart across a UUID space can enumerate what other teams hold. | |
| representation | Representation | representation selects the artefact. Unset means REPRESENTATION_EXTRACTED. | |
| range | ByteRange | range bounds the window served. Unset means "from the start". | |
| max_bytes | int64 | max_bytes is the caller's budget for THIS RESPONSE. 0 means the server default. A value above the server ceiling is clamped, and the clamp is named in truncation.detail rather than applied quietly. |
The server ceiling is also a bound on the WHOLE ARTEFACT, not only on the slice returned: an artefact larger than the server can hold in memory is an artefact it cannot hash, and it is refused with FAILED_PRECONDITION rather than served in pieces whose integrity nobody checked. Raising max_bytes does not raise that bound. | | verify_by_reassembly | bool | | verify_by_reassembly runs TK-2.8's check: assemble the document's chunks, remove the chunker's materialised overlap, and compare with the persisted extraction. OFF by default — it is a check, not the read path, and making it automatic would put de-overlap on every read for no user benefit. |
GetDocumentResponse
GetDocumentResponse is the byte-faithful read.
| Field | Type | Label | Description |
|---|---|---|---|
| content | bytes | content is the served bytes. Empty ONLY for a hard refusal; a document that is gone upstream or whose reference no longer resolves is served ALONGSIDE its marker (PRD §11, v1.3). | |
| representation | Representation | representation is which artefact was served. Never substituted: a request for one artefact is never answered with the other, because a silent fallback is exactly what M3's red direction forbids. | |
| truncation | Truncation | truncation is ALWAYS present and always says what was omitted. | |
| provenance | DocumentProvenance | provenance is where the bytes came from and when. | |
| currency | Currency | currency is what we know relative to upstream. Always present. | |
| reassembly_check | ReassemblyCheck | reassembly_check is TK-2.8's verdict. Always present, carrying REASSEMBLY_CHECK_STATE_NOT_REQUESTED when the caller did not ask. | |
| served_sha256 | string | served_sha256 is the SHA-256 of content as sent. This is what makes M3 checkable BY THE CALLER: when truncation.kind is TRUNCATION_KIND_NONE and content_provenance is CONTENT_PROVENANCE_PERSISTED, it equals the hash of the representation served — text_sha256 for EXTRACTED, raw_sha256 for RAW. |
ReassemblyCheck
ReassemblyCheck is TK-2.5 + TK-2.8 as a CHECK rather than a read path.
PRD acceptance: "assembled documents contain no duplicated overlap region" and "an integrity check asserts that bytes returned hash to the stored hash; a mismatch is surfaced and never resolved by silently preferring one artefact over the other."
| Field | Type | Label | Description |
|---|---|---|---|
| state | ReassemblyCheckState | state is the verdict. Never REASSEMBLY_CHECK_STATE_UNSPECIFIED on the wire. | |
| chunk_count | int32 | chunk_count is how many chunks were assembled. | |
| seams_de_overlapped | int32 | seams_de_overlapped is how many of the joins carried a materialised overlap that was removed. It is a COUNT and not a claim: rows written by an older chunker carry none, and reporting the count says so where "overlap removed" would be a promise the reconstruction cannot keep. | |
| max_seams | int32 | max_seams is the number of joins the chunk sequence HAS (chunk_count-1), the honest denominator for seams_de_overlapped. | |
| assembled_sha256 | string | assembled_sha256 is the SHA-256 of the de-overlapped assembly. | |
| persisted_sha256 | string | persisted_sha256 is the SHA-256 the assembly was compared against — the stored text_sha256. | |
| assembled_bytes | int64 | assembled_bytes is the size of the assembly. | |
| persisted_bytes | int64 | persisted_bytes is the size of the persisted extraction. | |
| detail | string | detail is a human-readable sentence for the state, so a text surface can render the verdict without re-deriving it from the numbers. |
Truncation
Truncation states what was served and what was omitted, in bytes.
TK-2.4: "when the request cannot be served whole, the response is explicitly marked truncated and STATES WHAT WAS OMITTED. Silent trimming is a defect." A boolean would satisfy "marked" and not "states what"; the counts are the difference between a marker and an answer.
| Field | Type | Label | Description |
|---|---|---|---|
| kind | TruncationKind | kind is why (or that) the response is bounded. | |
| total_bytes | int64 | total_bytes is the size of the WHOLE representation, always populated — it is the denominator without which served_bytes says nothing. | |
| served_bytes | int64 | served_bytes is len(content). Equal to total_bytes iff kind is TRUNCATION_KIND_NONE. | |
| offset | int64 | offset is the index of the first byte served. | |
| omitted_before | int64 | omitted_before is how many bytes precede the window (equal to offset). | |
| omitted_after | int64 | omitted_after is how many bytes follow the window. | |
| detail | string | detail is a human-readable sentence naming what was omitted and why, for surfaces that render text to a model rather than reading the counts. |
ContentProvenance
ContentProvenance says WHERE THE SERVED BYTES CAME FROM.
This is the field that keeps LLD §3.4 decision 1 honest. The read path is the persisted artefact; a document that has none (the legacy corpus, which T4 backfills as artefact_state='raw_unavailable' because nothing ever persisted its bytes) is still served — from its chunks — and SAYS SO. Without this field the two cases are one byte stream and the caller cannot tell a byte-faithful read from a reconstruction.
| Name | Number | Description |
|---|---|---|
| CONTENT_PROVENANCE_UNSPECIFIED | 0 | CONTENT_PROVENANCE_UNSPECIFIED is refused by the server's response validation. |
| CONTENT_PROVENANCE_PERSISTED | 1 | CONTENT_PROVENANCE_PERSISTED means the bytes came from the persisted artefact and were verified against its stored hash. This is the byte-faithful path and the only one M3 speaks about. |
| CONTENT_PROVENANCE_REASSEMBLED | 2 | CONTENT_PROVENANCE_REASSEMBLED means no persisted artefact exists for this version, so the bytes were reconstructed from the document's chunks with the chunker's materialised overlap removed. It is a RECONSTRUCTION of the segment sequence, not of the uploaded file: no hash is asserted about it and served_sha256 is over the reconstruction itself. |
| CONTENT_PROVENANCE_RENDERED_REPO_MAP | 3 | Virtual repository-map document rendered from its scoped stored sections; no duplicate blob or generic chunk copy exists. |
Currency
Currency is what we know about the served bytes RELATIVE TO UPSTREAM.
PRD §11 (v1.3): content is populated for GONE_UPSTREAM and REF_UNRESOLVED — the bytes are still valid and "never an empty result" would otherwise be satisfied by a bare error. Content is empty ONLY for a hard refusal.
| Name | Number | Description |
|---|---|---|
| CURRENCY_UNSPECIFIED | 0 | CURRENCY_UNSPECIFIED is refused by the server's response validation. |
| CURRENCY_CURRENT | 1 | CURRENCY_CURRENT means the copy was verified against upstream on this read. It requires F4's live fetch and is therefore NOT EMITTED IN PHASE 1 — claim bound C3 forbids describing freshness as anything but "as of the last sync" until F4 ships, and a server that said CURRENT without checking would be making exactly the claim C3 bounds. |
| CURRENCY_UNVERIFIED | 2 | CURRENCY_UNVERIFIED means the copy is the one persisted at ingest and has not been checked against upstream. This is every Phase-1 response. |
| CURRENCY_GONE_UPSTREAM | 3 | CURRENCY_GONE_UPSTREAM means upstream reported the document deleted. The persisted bytes are served ALONGSIDE the marker (PRD §11 row 1). |
| CURRENCY_REF_UNRESOLVED | 4 | CURRENCY_REF_UNRESOLVED means a path-shaped upstream reference no longer resolves — a DIFFERENT fact from a deletion we have observed (PRD §11, v1.2 identity correction). The persisted bytes are served alongside it. |
ReassemblyCheckState
ReassemblyCheckState is TK-2.8's verdict.
| Name | Number | Description |
|---|---|---|
| REASSEMBLY_CHECK_STATE_UNSPECIFIED | 0 | REASSEMBLY_CHECK_STATE_UNSPECIFIED is refused by the server's response validation. |
| REASSEMBLY_CHECK_STATE_NOT_REQUESTED | 1 | REASSEMBLY_CHECK_STATE_NOT_REQUESTED means verify_by_reassembly was false. The check is deliberately off by default: making it automatic would put TK-2.5's de-overlap on the hot path of every read, which is the cost LLD §3.4 decision 1 exists to avoid. |
| REASSEMBLY_CHECK_STATE_MATCH | 2 | REASSEMBLY_CHECK_STATE_MATCH means the de-overlapped assembly of the document's chunks is byte-identical to the persisted extraction. |
| REASSEMBLY_CHECK_STATE_DIVERGED | 3 | REASSEMBLY_CHECK_STATE_DIVERGED means they differ. This is a REPORTED STATE, not an error: the persisted extraction is still what was served, and PRD §11 forbids resolving the disagreement by silently preferring an artefact. The two hashes and both byte counts are in the message so the divergence is sizeable rather than merely announced. |
| REASSEMBLY_CHECK_STATE_NO_CHUNKS | 4 | REASSEMBLY_CHECK_STATE_NO_CHUNKS means the check was asked for and the document has no chunks visible to the caller, so there was nothing to assemble. Distinct from MATCH, which an empty-vs-empty comparison would otherwise produce. |
| REASSEMBLY_CHECK_STATE_NOT_APPLICABLE | 5 | REASSEMBLY_CHECK_STATE_NOT_APPLICABLE means there is nothing this check could assert: the raw representation was served (chunks are produced from the EXTRACTION, so assembling them can only ever reproduce the extraction), or the served bytes ARE the assembly (CONTENT_PROVENANCE_REASSEMBLED, where comparing them to themselves would be a tautology reported as a pass). |
Representation
Representation names WHICH artefact of a document version is being addressed.
A document has two persisted artefacts and they are different byte sequences for four of the six content types the extractor handles. Asking for one and silently receiving the other is the failure M3's red direction names, so the value is echoed on every response and the server never substitutes.
| Name | Number | Description |
|---|---|---|
| REPRESENTATION_UNSPECIFIED | 0 | REPRESENTATION_UNSPECIFIED means the caller did not choose. On a REQUEST it is read as REPRESENTATION_EXTRACTED (the useful default for a model). On a RESPONSE it is refused by the server's own validation — a response that does not say what it served is exactly the ambiguity this enum exists to remove. |
| REPRESENTATION_EXTRACTED | 1 | REPRESENTATION_EXTRACTED is the persisted extracted text, hashed by text_sha256 and dated by extractor_version. |
| REPRESENTATION_RAW | 2 | REPRESENTATION_RAW is the persisted original bytes, hashed by raw_sha256. |
TruncationKind
TruncationKind says WHY the served bytes are not the whole representation — or that they are.
| Name | Number | Description |
|---|---|---|
| TRUNCATION_KIND_UNSPECIFIED | 0 | TRUNCATION_KIND_UNSPECIFIED is refused by the server's response validation. It is the value a future return statement gets by forgetting, which is precisely the case that must not be able to reach a caller. |
| TRUNCATION_KIND_NONE | 1 | TRUNCATION_KIND_NONE means the whole representation was served. |
| TRUNCATION_KIND_RANGE | 2 | TRUNCATION_KIND_RANGE means the caller asked for a bounded window. |
| TRUNCATION_KIND_BUDGET | 3 | TRUNCATION_KIND_BUDGET means a byte budget (the caller's max_bytes, or the server default when it was 0) cut the response short. |
upsquad/knowledge/v1/knowledge.proto
AgentSourceOverride
AgentSourceOverride is one persisted disable row, including its original audit metadata. A row may remain after the source leaves the effective availability set; it does not grant access to that source.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id identifies the source disabled for this agent. | |
| created_by | string | created_by is the member who originally disabled it. | |
| created_at | google.protobuf.Timestamp | created_at is the original disable time; repeated disable is idempotent. |
AttachSourceToUnitRequest
AttachSourceToUnitRequest tags a source onto an org_unit OR org-wide. The acting member is taken from the caller's scope, not this message.
Org-attach contract (#1554): set scope='org' and leave unit_id empty to make the source retrievable org-wide (every pillar/team inherits it). For a pillar/team attach set scope='unit' (or leave it empty — 'unit' is the default) and supply unit_id. As a back-compat shim for the client placeholder (client#389), unit_id="org" with an empty scope is also treated as an org-attach; new clients SHOULD send scope='org' with an empty unit_id.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the knowledge source to attach (required). | |
| unit_id | string | unit_id is the org_units.id (pillar/team) to attach it to. Required for a unit attach; MUST be empty for an org attach (scope='org'). | |
| visibility | string | visibility is one of 'inherit_down' | |
| scope | string | scope is 'unit' (default — a pillar/team attach, requires unit_id) or 'org' (an org-wide attach, unit_id must be empty). (#1554.) |
AttachSourceToUnitResponse
AttachSourceToUnitResponse returns the created (or revived) binding.
| Field | Type | Label | Description |
|---|---|---|---|
| binding | SourceUnitBinding | binding is the resulting source⇄unit binding. |
CreateSourceRequest
CreateSourceRequest creates a new knowledge source in the org-owned catalog. The owning org and the creating member are taken from the caller's scope, not from this message. A source no longer carries an owning scope at creation (HLD-C §3.1, RA2 REPLACE) — attach it to one-or-many pillars/teams afterwards with AttachSourceToUnit. Fields 1/2 (the legacy owning_scope / unit_id) were dropped in the founder-approved breaking change DC-3 (#1382/#1377); their numbers + names are reserved.
| Field | Type | Label | Description |
|---|---|---|---|
| name | string | name is the human-readable source name (required, non-empty). | |
| description | string | description is an optional free-text description. | |
| src_type | string | src_type is one of the registered source types. Only upload | |
| refresh_interval_seconds | int32 | refresh_interval_seconds is the desired auto-refresh cadence in seconds; 0 (the default) means auto-refresh is off. Persisted as NULL when 0. (#1367.) | |
| criticality | string | criticality is one of 'low' | |
| url | string | url is the connector fetch target. Required and non-empty when src_type='web' (an https URL the connector SSRF-screens at fetch time, #1375) or src_type='gdrive' (a Google Drive folder URL or raw folder id, #1430); must be empty for all other source types. The DB CHECK is the backstop. |
CreateSourceResponse
CreateSourceResponse returns the created source.
| Field | Type | Label | Description |
|---|---|---|---|
| source | Source | source is the newly created source. |
DeleteSourceRequest
DeleteSourceRequest soft-deletes a source and hard-deletes its chunks.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID. |
DeleteSourceResponse
DeleteSourceResponse reports the outcome of a delete.
| Field | Type | Label | Description |
|---|---|---|---|
| chunks_removed | int32 | chunks_removed is the number of rag_chunks rows cascade-deleted. |
DetachSourceFromUnitRequest
DetachSourceFromUnitRequest soft-deletes a source⇄unit binding, or the source's org-wide binding when scope='org' (#1554).
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the attached source (required). | |
| unit_id | string | unit_id is the org_units.id to detach it from. Required for a unit detach; MUST be empty for an org detach (scope='org'). As a back-compat shim, unit_id="org" with an empty scope is treated as an org detach. | |
| scope | string | scope is 'unit' (default) or 'org' (detach the org-wide binding). (#1554.) |
DetachSourceFromUnitResponse
DetachSourceFromUnitResponse reports whether an active binding was removed.
| Field | Type | Label | Description |
|---|---|---|---|
| detached | bool | detached is true when an active binding was soft-deleted; false when there was no active binding to remove. |
DriveTypeBreakdown
DriveTypeBreakdown tallies the previewed files of one content category so the UI can show "12 PDFs (40 MB), 3 Google Docs, 2 unsupported".
| Field | Type | Label | Description |
|---|---|---|---|
| category | string | category is a coarse content bucket: 'gdoc' | |
| file_count | int32 | file_count is the number of files in this category. | |
| total_bytes | int64 | total_bytes is the summed binary size of files in this category. Google- native files (gdoc/gslides/gsheets) report 0 bytes in Drive (they have no binary blob until exported), so their size is not counted here. |
EffectiveSourceEntry
EffectiveSourceEntry is one resolved binding tagged with its provenance.
| Field | Type | Label | Description |
|---|---|---|---|
| binding | SourceUnitBinding | binding is the resolved source⇄unit binding. | |
| effective_source | string | effective_source is the provenance: 'direct' | |
| source_unit_id | string | source_unit_id is the unit the binding was found on (the direct unit, the inherit_down ancestor, or the shared_siblings sibling). Empty for an 'org' provenance binding. |
GetSourceRequest
GetSourceRequest fetches a single source by id.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID. |
GetSourceResponse
GetSourceResponse returns the requested source.
| Field | Type | Label | Description |
|---|---|---|---|
| source | Source | source is the requested source. |
GetSourceStatusRequest
GetSourceStatusRequest fetches ingestion status for a source.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID. |
GetSourceStatusResponse
GetSourceStatusResponse reports ingestion progress for a source.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the source UUID. | |
| sync_status | string | sync_status is one of 'empty' | |
| doc_count | int32 | doc_count is the number of ingested documents. | |
| chunk_count | int32 | chunk_count is the total number of chunks for the source (authoritative COUNT over rag_chunks). | |
| embedded_chunk_count | int32 | embedded_chunk_count is the number of chunks with embeddings computed. (Maintained by FW3-b's embed worker; 0 until ingestion lands.) | |
| pending_chunk_count | int32 | pending_chunk_count is chunk_count - embedded_chunk_count. |
IngestDocumentRequest
IngestDocumentRequest feeds one document into a source. The owning org and the acting member are taken from the caller's scope, never from this message.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the knowledge_sources UUID to ingest into (required). The source must be visible to the caller's scope and of an ingestable type (upload | |
| filename | string | filename is the original document filename, retained on each chunk's metadata for provenance (optional but recommended). | |
| content_type | string | content_type selects the text extractor: one of 'md' | |
| content | bytes | content is the raw document bytes. Size caps (founder Design Call D5): 10 MB for md |
IngestDocumentResponse
IngestDocumentResponse reports the outcome of an ingestion.
| Field | Type | Label | Description |
|---|---|---|---|
| source_doc_id | string | source_doc_id is the deterministic per-document identity (derived from the content_hash) stamped on every chunk of this document. | |
| chunk_count | int32 | chunk_count is the number of chunks created for this document (0 on an idempotent hit). | |
| token_count | int32 | token_count is the total token count across the document's chunks. | |
| idempotent_hit | bool | idempotent_hit is true when this document's content_hash was already ingested for the source; the call made no changes. | |
| content_hash | string | content_hash is the SHA-256 hex digest of the raw document bytes. |
ListAgentSourceOverridesRequest
ListAgentSourceOverridesRequest selects an agent UUID within the authenticated organisation's override rows; it does not establish ownership of the agent.
| Field | Type | Label | Description |
|---|---|---|---|
| agent_id | string | agent_id is a required agent UUID. |
ListAgentSourceOverridesResponse
ListAgentSourceOverridesResponse contains all disable rows written by the authenticated organisation for the requested agent, ordered by source_id. Absence means this organisation has not disabled that source; it does not establish effective enablement. A pre-existing cross-org write/enforcement gap can hide an enforced disable from this read under BYPASSRLS connections: https://github.com/upsquad-ai/upsquad-core/issues/3413. Availability must still come from ListEffectiveSources. Errors, unimplemented RPCs and incomplete responses cannot establish even caller-org absence. No rows are truncated or filtered against the effective set, and this read is not cached. Retrieval-result freshness after writes is tracked separately in https://github.com/upsquad-ai/upsquad-core/issues/3415.
| Field | Type | Label | Description |
|---|---|---|---|
| overrides | AgentSourceOverride | repeated | overrides contains every persisted disable row for this org and agent. |
ListEffectiveSourcesRequest
ListEffectiveSourcesRequest resolves the effective source set. Exactly one of the three selectors must be set; the others must be empty.
| Field | Type | Label | Description |
|---|---|---|---|
| unit_id | string | unit_id resolves the effective set anchored at a single pillar/team. | |
| member_id | string | member_id resolves the effective set across all units a member belongs to. | |
| agent_id | string | agent_id resolves the effective set for an agent (agents are members in the unified org_unit tree, so this resolves the same way as member_id). |
ListEffectiveSourcesResponse
ListEffectiveSourcesResponse returns the resolved, de-duplicated set.
| Field | Type | Label | Description |
|---|---|---|---|
| entries | EffectiveSourceEntry | repeated | entries are the effective sources, one per distinct source_id. |
ListSourceUnitsRequest
ListSourceUnitsRequest lists the units a source is attached to.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the knowledge source (required). |
ListSourceUnitsResponse
ListSourceUnitsResponse returns a source's active bindings.
| Field | Type | Label | Description |
|---|---|---|---|
| bindings | SourceUnitBinding | repeated | bindings are the source's active source⇄unit attachments. GRANTS ONLY — withholds are reported by ListSourceWithholds (#3222). |
ListSourceWithholdsRequest
ListSourceWithholdsRequest lists the active withholds on one unit.
| Field | Type | Label | Description |
|---|---|---|---|
| unit_id | string | unit_id is the org_units.id whose withholds to list (required). This lists the withholds set AT this unit, not the ones it inherits from an ancestor — "what did this unit's Manager take away", which is the set that unit's Manager can act on. |
ListSourceWithholdsResponse
ListSourceWithholdsResponse returns the unit's active withholds.
| Field | Type | Label | Description |
|---|---|---|---|
| withholds | SourceWithhold | repeated | withholds are the unit's active binding_kind='withhold' rows, ordered by source_id. |
ListSourcesRequest
ListSourcesRequest pages the org-owned source catalog. After the RA2 REPLACE (HLD-C §3.1) a source has no owning scope, so the owning_scope/unit_id/ include_inherited filters are retained for wire-compatibility but IGNORED by the server — use ListEffectiveSources(unit_id) for the "RAG on this pillar/team" view with provenance. They are not removed (no further proto break) but carry no semantics.
| Field | Type | Label | Description |
|---|---|---|---|
| owning_scope | string | Deprecated: ignored after HLD-C (the catalog is org-wide). Was an 'org' | |
| unit_id | string | Deprecated: ignored after HLD-C. Was a single pillar/team filter. | |
| include_inherited | bool | Deprecated: ignored after HLD-C. Was the inherit-up listing flag. | |
| page_size | int32 | page_size bounds the page (default 50, max 100). | |
| page_token | string | page_token is the opaque cursor from a previous response. |
ListSourcesResponse
ListSourcesResponse is a page of sources.
| Field | Type | Label | Description |
|---|---|---|---|
| sources | Source | repeated | sources is the page of visible sources. |
| next_page_token | string | next_page_token is the cursor for the next page; empty when exhausted. |
PreviewDriveFolderRequest
PreviewDriveFolderRequest asks the Drive folder connector to size a folder before a gdrive source is created (#1430). It carries no source id — nothing is persisted.
| Field | Type | Label | Description |
|---|---|---|---|
| folder | string | folder is the Google Drive folder URL (e.g. https://drive.google.com/drive/folders/<ID>) or a raw folder id. The folder must already be shared (Viewer) with the connector's service-account email. |
PreviewDriveFolderResponse
PreviewDriveFolderResponse reports the size of a Drive folder without ingesting it.
| Field | Type | Label | Description |
|---|---|---|---|
| total_bytes | int64 | total_bytes is the summed binary size of all INGESTABLE files (excludes unsupported types and Google-native files, which report 0 binary bytes). It is a download-size estimate so the UI can warn before a large sync. | |
| file_count | int32 | file_count is the number of ingestable files the sync would process. | |
| unsupported_count | int32 | unsupported_count is the number of files skipped because their MIME type is not ingestable. | |
| breakdown | DriveTypeBreakdown | repeated | breakdown is the per-category tally (one entry per non-empty category). |
| truncated | bool | truncated is true when the folder hit the preview scan caps (max file count or max recursion depth); the totals are then a lower bound, not exact. |
RefreshSourceRequest
RefreshSourceRequest triggers a manual re-fetch of a source.
| Field | Type | Label | Description |
|---|---|---|---|
| source_id | string | source_id is the source UUID to refresh (required). |
RefreshSourceResponse
RefreshSourceResponse reports the outcome of a refresh trigger.
| Field | Type | Label | Description |
|---|---|---|---|
| status | string | status is a machine-readable outcome: 'manual' — upload | |
| message | string | message is a human-readable explanation of the status. |
SetAgentSourceEnabledRequest
SetAgentSourceEnabledRequest toggles a per-agent disable override.
| Field | Type | Label | Description |
|---|---|---|---|
| agent_id | string | agent_id is the agent whose source visibility is being changed. | |
| source_id | string | source_id is the source being enabled/disabled for the agent. | |
| enabled | bool | enabled=false inserts a disable override; enabled=true removes it. |
SetAgentSourceEnabledResponse
SetAgentSourceEnabledResponse echoes the resulting enabled state.
| Field | Type | Label | Description |
|---|---|---|---|
| enabled | bool | enabled is the effective state after the call (true = agent retrieves the source, false = disabled). |
SetSourceWithholdRequest
SetSourceWithholdRequest sets or clears a Manager subtree-withhold on a knowledge source for a unit (#3222). The acting Manager is taken from the caller's scope, never from this message.
| Field | Type | Label | Description |
|---|---|---|---|
| unit_id | string | unit_id is the org_units.id at which the withhold applies (required). The caller MUST be this unit's Manager (org_units.manager_member_id). The withhold scopes to this unit AND its whole subtree. |
There is no org-grain form of this request, and that is a constraint rather than an omission: migration 231's ksu_withhold_is_unit_scoped_check makes an org-scoped withhold unstorable, because such a row names no subtree — the grant predicate refuses to count it and the subtract pass never finds it, so it would be an operator action that reports success and changes nothing. | | source_id | string | | source_id is the knowledge_sources.id to withhold / un-withhold for the subtree (required). | | withheld | bool | | withheld=true sets the withhold (subtracts the source from the subtree); withheld=false clears it (the subtree may again inherit or be granted the source). Both directions are idempotent. | | reason | string | | reason is an optional free-text note recorded on the audit row. |
SetSourceWithholdResponse
SetSourceWithholdResponse reports the resulting withhold state.
| Field | Type | Label | Description |
|---|---|---|---|
| unit_id | string | unit_id echoes the unit the withhold applies at. | |
| source_id | string | source_id echoes the withheld source. | |
| withheld | bool | withheld is the resulting state (true = an active withhold now exists). |
Source
Source is a scope-agnostic, org-owned knowledge corpus. Its retrieval visibility is decided entirely by its knowledge_source_units bindings (HLD-C §3.1), NOT by a single owning scope. Fields 4/5 (the legacy owning_scope / unit_id, HLD-A D3 1:1 model) were dropped in the RA2 REPLACE (#1382/#1377, founder-approved breaking change DC-3); their numbers + names are reserved so they can never be re-used.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source's UUID. | |
| name | string | name is the human-readable source name. | |
| description | string | description is an optional free-text description. | |
| src_type | string | src_type is one of 'upload' | |
| sync_status | string | sync_status is one of 'empty' | |
| doc_count | int32 | doc_count is the number of ingested documents in the source. | |
| chunk_count | int32 | chunk_count is the cached chunk count (authoritative count is COUNT(rag_chunks WHERE source_id = id)). | |
| created_by | string | created_by is the member id that created the source. | |
| created_at | google.protobuf.Timestamp | created_at is the source creation timestamp. | |
| updated_at | google.protobuf.Timestamp | updated_at is the last-modification timestamp. | |
| last_refreshed_at | google.protobuf.Timestamp | last_refreshed_at is the timestamp of the most recent successful refresh (manual re-fetch or scheduled connector sync). Unset until the source has been refreshed at least once. (MVP RAG refresh, #1367.) | |
| refresh_interval_seconds | int32 | refresh_interval_seconds is the desired auto-refresh cadence in seconds. 0 means auto-refresh is off (the column is NULL in the DB). The scheduled connector worker that honours this cadence is Track D; FW3 persists the value only. (MVP RAG refresh, #1367.) | |
| criticality | string | criticality is one of 'low' | |
| url | string | url is the connector fetch target. For src_type='web' it is the page URL (the Web URL connector enforces an https-only scheme allowlist + SSRF egress guard, #1375). For src_type='gdrive' it is the Google Drive folder URL or raw folder id the connector lists + ingests (the Drive folder connector, #1430). Empty for all other source types. |
SourceUnitBinding
SourceUnitBinding mirrors a knowledge_source_units row: a source attached to one org_unit with a visibility mode, OR an org-wide attachment (#1554). (RA1, #1381, migration 107; org scope migration 116.)
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the binding's UUID. | |
| org_id | string | org_id is the owning organisation. | |
| source_id | string | source_id is the attached knowledge source. | |
| unit_id | string | unit_id is the org_units.id the source is attached to. Empty for an org-scoped binding (owning_scope='org'). | |
| visibility | string | visibility is one of 'inherit_down' | |
| configured_by | string | configured_by is the member id that created the binding. | |
| created_at | google.protobuf.Timestamp | created_at is the binding creation timestamp. | |
| updated_at | google.protobuf.Timestamp | updated_at is the last-modification timestamp. | |
| owning_scope | string | owning_scope is 'unit' (a pillar/team attachment; unit_id is set) or 'org' (an org-wide attachment; unit_id is empty). An org binding is unioned into every scope's effective set. (#1554, migration 116.) |
SourceWithhold
SourceWithhold is ONE active knowledge_source_units row with binding_kind='withhold' (#3222, migration 231).
It is a distinct message from SourceUnitBinding rather than a flag on it: a withhold carries no visibility mode that means anything (the subtract pass is scoped by the unit chain, not by visibility) and no owning_scope other than 'unit', so the fields SourceUnitBinding would contribute are precisely the ones that would mislead a reader.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the withhold row's UUID. | |
| source_id | string | source_id is the source being withheld. | |
| unit_id | string | unit_id is the org_units.id the withhold applies at. Its whole subtree is covered. | |
| configured_by | string | configured_by is the member id of the Manager who set the withhold. | |
| created_at | google.protobuf.Timestamp | created_at is when the withhold row was first written. | |
| updated_at | google.protobuf.Timestamp | updated_at is the last-modification timestamp. |
UpdateSourceRequest
UpdateSourceRequest mutates a source's editable attributes. Every mutable
field is optional: when a field is unset it is left unchanged, when set it
replaces the stored value. id is required.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | id is the source UUID to update (required). | |
| name | string | optional | name, when set, replaces the source name (must be non-empty when present). |
| description | string | optional | description, when set, replaces the description (empty string clears it). |
| refresh_interval_seconds | int32 | optional | refresh_interval_seconds, when set, replaces the auto-refresh cadence; 0 turns auto-refresh off (persisted as NULL). |
| criticality | string | optional | criticality, when set, replaces the criticality ('low' |
| url | string | optional | url, when set, replaces the fetch target of a src_type='web' source. Must be a non-empty https URL; only meaningful for web sources. (#1375.) |
UpdateSourceResponse
UpdateSourceResponse returns the updated source.
| Field | Type | Label | Description |
|---|---|---|---|
| source | Source | source is the source after the update. |
KnowledgeService
KnowledgeService is the external (Connect / gRPC) surface for knowledge source lifecycle management. All operations are tenant-scoped via JWT-derived scope claims and PostgreSQL row-level security; the owning org and the acting member are taken from the request scope, never from the request body.
Access control (HLD §7, founder Design Call D6):
- CreateSource / DeleteSource / SetAgentSourceEnabled: clearance >= L3
AND the
knowledge.managerole capability. - ListSources / GetSource / GetSourceStatus: clearance >= L1 AND the
knowledge.readcapability; results are further filtered by the scope-visibility RLS policy on knowledge_sources.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| CreateSource | CreateSourceRequest | CreateSourceResponse | CreateSource registers a new knowledge source in the org-owned catalog (HLD-C §3.1 — sources are scope-agnostic; attach them to pillars/teams afterwards with AttachSourceToUnit). The owning org and creator are derived from the caller's scope. The source starts empty (sync_status='empty') unless its src_type is a not-yet-implemented connector, in which case it is created 'disabled'. |
| ListSources | ListSourcesRequest | ListSourcesResponse | ListSources pages the org-owned source catalog (org-isolation RLS only; after HLD-C there is no per-scope owning filter). Use ListEffectiveSources to see the resolved set for a pillar/team/agent with provenance. |
| GetSource | GetSourceRequest | GetSourceResponse | GetSource returns a single source by id, subject to the same scope-visibility policy as ListSources. |
| UpdateSource | UpdateSourceRequest | UpdateSourceResponse | UpdateSource mutates the editable attributes of a source (name, description, auto-refresh cadence, criticality). All update fields are optional: an unset field is left unchanged. Clearance >= L5 AND knowledge.manage (MVP edit floor, #1367). src_type is immutable; scope is managed via AttachSourceToUnit, not UpdateSource. (MVP RAG refresh/ criticality, #1367.) |
| RefreshSource | RefreshSourceRequest | RefreshSourceResponse | RefreshSource triggers a manual re-fetch of a source's content. For the upload |
| DeleteSource | DeleteSourceRequest | DeleteSourceResponse | DeleteSource soft-deletes the source row and hard-deletes its derived chunks via ON DELETE CASCADE (founder Design Call D2). A tamper-evident audit row records the deletion and the count of chunks removed. The retained artifact for regulated tenants is the source document, not the reproducible chunks. |
| SetAgentSourceEnabled | SetAgentSourceEnabledRequest | SetAgentSourceEnabledResponse | SetAgentSourceEnabled toggles a per-agent disable override for a source. enabled=false inserts an override row (the agent stops retrieving the source even though its scope grants availability); enabled=true removes the row. Availability can only be narrowed by an agent, never widened. |
| ListAgentSourceOverrides | ListAgentSourceOverridesRequest | ListAgentSourceOverridesResponse | ListAgentSourceOverrides reads the live disable rows written by the authenticated organisation for an agent UUID. Requires L1 and knowledge.read. This is separate from ListEffectiveSources availability and provenance. |
| GetSourceStatus | GetSourceStatusRequest | GetSourceStatusResponse | GetSourceStatus reports ingestion progress for a source so the UI can render a sync indicator: total documents, total chunks, and the embedded-vs-pending split. (Embedded/pending are populated by FW3-b's embed worker; FW3-a returns the cached counts and the persisted status.) |
| PreviewDriveFolder | PreviewDriveFolderRequest | PreviewDriveFolderResponse | PreviewDriveFolder lists a Google Drive folder (the Drive folder connector, #1430) WITHOUT ingesting anything and returns the overall size + file count + a per-type breakdown so the UI can show the user how big a sync will be BEFORE they commit to creating the gdrive source. The folder must already be shared (Viewer) with the connector's service-account email; the request carries the folder URL or raw folder id. This is a read-only dry-run: no knowledge_sources row is created and nothing is chunked or embedded. Clearance >= L5 AND knowledge.manage (same floor as CreateSource — only a source manager previews a folder, and the file listing is sensitive). When the gdrive connector is not configured on the deployment (no GDRIVE_CREDENTIALS_FILE) the call returns FailedPrecondition. |
| IngestDocument | IngestDocumentRequest | IngestDocumentResponse | IngestDocument feeds one document into a source's corpus (FW3-b, #1325). The server extracts text from the supplied bytes (markdown / html / pdf / plain), chunks it with the existing headings-aware chunker, embeds the chunks via the existing embedding pipeline, and persists them to rag_chunks + context_embeddings stamped with the source_id and the source's owning scope. Ingestion is idempotent on the document's content_hash: re-sending identical bytes for the same source is a no-op that returns the prior result (idempotent_hit=true). Access control: clearance >= L2 (founder Design Call D6 Ingest floor) AND the knowledge.manage capability. Only upload |
| AttachSourceToUnit | AttachSourceToUnitRequest | AttachSourceToUnitResponse | AttachSourceToUnit tags a source onto an org_unit (pillar/team) with a visibility mode, exactly like attaching a tool to a unit (org_unit_tools, migration 064). A source may be attached to many units; availability is then computed by the same org→pillar→team inheritance walk the tool model uses. The acting member (configured_by) is taken from the caller's scope, never the request body. Clearance >= L5 (the consolidated knowledge management floor) AND knowledge.manage. (RA1, #1381, HLD-C §7.) |
| DetachSourceFromUnit | DetachSourceFromUnitRequest | DetachSourceFromUnitResponse | DetachSourceFromUnit soft-deletes a source⇄unit binding (re-attach later is allowed). Clearance >= L5 AND knowledge.manage. (RA1, #1381, HLD-C §7.) |
| ListSourceUnits | ListSourceUnitsRequest | ListSourceUnitsResponse | ListSourceUnits returns the units a source is currently attached to (its active GRANT bindings). It does NOT report withholds — a withhold is a restriction and this response says "attached", which is the one description of a withhold that is false. Read withholds with ListSourceWithholds. Clearance >= L1 AND knowledge.read. (RA1, #1381.) |
| SetSourceWithhold | SetSourceWithholdRequest | SetSourceWithholdResponse | SetSourceWithhold sets or clears a Manager subtree-WITHHOLD on a knowledge source for a unit (TK-7.3 / F5c, #3222). A withhold is a knowledge_source_units row with binding_kind='withhold' (migration 231) keyed to (source, unit); it SUBTRACTS that source from the effective knowledge set of the unit AND its whole subtree, beating every grant however that grant entered the union — direct, inherited-down, shared-siblings, org-wide, or an accepted cross-offer. |
AUTHORITY (founder decision on #3222, Option A): the unit's Manager (org_units.manager_member_id) — the SAME authority as the MCP binding approval machinery (ApproveMCPServerBinding / SetMCPServerWithhold), no new governance actor. The root unit's Manager reaches org-wide; a leaf's Manager reaches only their own subtree. A non-Manager caller is permission_denied and a unit with no Manager is failed_precondition (fail closed).
It is a DIRECT write and not a pending→approve two-step, exactly as MCP's own withhold is: a restriction that sits inert while awaiting approval is a deny that does not deny, which is the fail-open shape of a fail-closed control. The approval machinery contributes its AUTHORITY and its AUDIT surface here, not its pending state.
Capability knowledge.manage, unit-scoped. There is deliberately NO clearance floor — Manager identity IS the authority, matching SetMCPServerWithhold. Emits a knowledge_subtree_withheld audit row on both set and clear. |
| ListSourceWithholds | ListSourceWithholdsRequest | ListSourceWithholdsResponse | ListSourceWithholds returns the ACTIVE withholds on one unit — the read the Team page renders withhold state from (F7, upsquad-client#857), and the Manager's view of the restrictions they have set.
It is a separate RPC rather than a binding_kind field on ListSourceUnits because those two responses answer opposite questions ("what does this unit have" vs "what has been taken away from it"), and one list that mixes them relies on every existing reader starting to check a discriminator it never had to check before. Every row here IS a withhold by construction.
Clearance >= L1 AND knowledge.read, unit-scoped: a restriction on a team is visible to that team, not only to the Manager who set it (PRD #2995 R6 — the named failure mode is a Manager believing a withhold is stronger than it is, and an unreadable restriction is that failure with the volume up). |
| ListEffectiveSources | ListEffectiveSourcesRequest | ListEffectiveSourcesResponse | ListEffectiveSources resolves the effective source set for exactly one of {unit_id, member_id, agent_id} via the org→pillar→team inheritance walk (direct ∪ inherited-down ∪ shared-siblings; de-dup direct > inherited > sibling), each entry tagged with its provenance. Clearance >= L1 AND knowledge.read. (RA1, #1381, HLD-C §4/§7.) |
| GetDocument | GetDocumentRequest | GetDocumentResponse | GetDocument returns ONE document version whole, or a bounded window of it, from the artefact PERSISTED AT INGEST (T3 #3075, LLD #3072 §3.4, HLD §4.5). Retrieval hands back the chunk that matched; this hands back the document behind it, which is #2619's relief and PRD #2995's goal G2.
Reassembly from chunks is TK-2.8's CHECK and NOT the read path: serving from reassembly would make every read depend on chunk hygiene and would put the de-overlap on the hot path for no user benefit. It runs only when the request asks (verify_by_reassembly), and its verdict is a reported state — never a silent preference for one artefact over the other.
truncation and currency are non-optional in the sense that matters: the server validates its OWN response and refuses to emit an _UNSPECIFIED in either. NFR-4 says no path may return content that LOOKS whole and is not, and a field that can be omitted is a path that can look whole.
Access control: knowledge.read AND NO CLEARANCE FLOOR. NG-3 binds content retrieval; knowledge is TEAM-scoped, and the team gate is the effective source set — the SAME set retrieval resolves, so a document reachable by search is reachable here and one that is not, is not. The knowledge MANAGEMENT floors above are untouched by this and must not be extended over it (PRD #2995 claim bound C2). |
upsquad/knowledge/v1/repo.proto
BindRepoCredentialRequest
BindRepoCredentialRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| repo_id | string | Registered repository id scoped to the named team. | |
| credential_id | string | Exact isolated team credential id. | |
| expected_credential_epoch | int64 | Exact credential epoch observed by the caller; stale writes are refused. | |
| expected_binding_revision | int64 | Zero means no binding exists; a replacement names its current revision. |
BindRepoCredentialResponse
BindRepoCredentialResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| connection | RepoConnectionState | Persisted sanitized source-connection state. |
CheckTeamRepoConnectionRequest
CheckTeamRepoConnectionRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| repo_id | string | Registered repository id scoped to the named team. | |
| expected_binding_revision | int64 | Exact binding revision observed by the caller; stale writes are refused. |
CheckTeamRepoConnectionResponse
CheckTeamRepoConnectionResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| connection | RepoConnectionState | Persisted sanitized source-connection state. |
ConfigureRepoMapGeneratorRequest
ConfigureRepoMapGeneratorRequest never takes an org id or credentials.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact team managed by the authenticated caller. | |
| expected_revision | int64 | Zero creates; an existing setup requires its current revision. | |
| options | RepoMapGeneratorOptions | Explicit finite options to save or resume. |
ConfigureRepoMapGeneratorResponse
ConfigureRepoMapGeneratorResponse reports the committed step, not fake readiness.
| Field | Type | Label | Description |
|---|---|---|---|
| setup | RepoMapGeneratorState | Actual setup state after the bounded owner operation. |
CreateTeamRepoCredentialRequest
CreateTeamRepoCredentialRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| provider | RepoProvider | Declared provider; V1b accepts GitHub only. | |
| provider_host | string | Canonical host; V1b accepts github.com only. | |
| label | string | Human-readable connection name. | |
| secret | TeamRepoCredentialSecret | Write-only replacement credential material. |
CreateTeamRepoCredentialResponse
CreateTeamRepoCredentialResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| credential | TeamRepoCredential | Redacted persisted credential metadata. |
Divergence
Divergence is what a regeneration WOULD have written to a locked section.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | Divergence row id; the handle SetRepoMapSectionLock acknowledges. | |
| proposed_body | string | The body the run proposed. Verbatim: a curator deciding whether to accept the drift needs the text, not a summary of it. | |
| run_id | string | The generation run that proposed it. | |
| generated_commit | string | The commit that run was pinned to. | |
| detected_at | google.protobuf.Timestamp | When it was detected. |
GeneratedSection
GeneratedSection is one section a generation run produced.
| Field | Type | Label | Description |
|---|---|---|---|
| kind | SectionKind | Which section it is. | |
| body | string | The generated text. |
GetRepoMapGeneratorRequest
GetRepoMapGeneratorRequest selects one authenticated team's setup.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Team whose current setup is requested. |
GetRepoMapGeneratorResponse
GetRepoMapGeneratorResponse remains truthful when nothing has been configured.
| Field | Type | Label | Description |
|---|---|---|---|
| setup | RepoMapGeneratorState | Current setup including absence, pending dependencies and server authority. |
GetRepoMapRequest
GetRepoMapRequest reads one repository's map.
| Field | Type | Label | Description |
|---|---|---|---|
| repo_id | string | The registry entry id. Either this or path_with_namespace is required. | |
| path_with_namespace | string | The upstream path, for callers holding a path rather than an id. | |
| team_unit_id | string | The team unit to resolve path_with_namespace within. Required when path_with_namespace is used. | |
| provider | RepoProvider | Optional path qualifier; cannot accompany repo_id. | |
| provider_host | string | optional | Omitted: no host filter. Explicit empty: unknown-host legacy namespace. |
GetRepoMapResponse
GetRepoMapResponse carries the map and its read-time staleness.
| Field | Type | Label | Description |
|---|---|---|---|
| map | RepoMap | The map. Its staleness is never absent. |
GitHubRepoAppSecret
GitHubRepoAppSecret is write-only. Use a dedicated read-only App; the PEM's provider-side authority can be broader than the token this adapter mints.
| Field | Type | Label | Description |
|---|---|---|---|
| app_id | string | Numeric App id from its settings, not its client id or installation id. | |
| private_key_pem | string | RSA private key, never returned, logged, or included in audit metadata. |
GitHubRepoPATSecret
GitHubRepoPATSecret requires a fine-grained, selected-repository PAT with Contents:read and Metadata:read. Opaque permissions cannot be verified by possession; acknowledgement never claims the token was down-scoped.
| Field | Type | Label | Description |
|---|---|---|---|
| token | string | Write-only fine-grained PAT; never returned or logged. | |
| acknowledge_unverified_scope | bool | Explicit acknowledgement that opaque PAT permissions cannot be proven. | |
| expires_at | google.protobuf.Timestamp | Declared credential expiry; omitted when no expiry is declared. |
ListRepoMapRunsRequest
ListRepoMapRunsRequest scopes and bounds history.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team. | |
| repo_id | string | Registered repository. | |
| page_size | int32 | Positive maximum capped at one hundred. | |
| page_token | string | Opaque cursor bound to org/team/repository. |
ListRepoMapRunsResponse
ListRepoMapRunsResponse contains no source bytes.
| Field | Type | Label | Description |
|---|---|---|---|
| runs | RepoMapGenerationRun | repeated | Sanitized history in admission order. |
| next_page_token | string | Empty only when no further page exists. |
ListReposRequest
ListReposRequest pages a team's registry.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | The team unit whose registry to read. Required. | |
| include_archived | bool | Include repositories archived upstream. Default false. | |
| page_size | int32 | Page size; clamped server-side. | |
| page_token | string | Opaque page token. |
ListReposResponse
ListReposResponse is one page of a team's registry.
| Field | Type | Label | Description |
|---|---|---|---|
| repos | Repo | repeated | The page. |
| next_page_token | string | Token for the next page; empty when the page is the last. |
ListTeamRepoCredentialsRequest
ListTeamRepoCredentialsRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| page_size | int32 | Page size, server-clamped to at most 100. | |
| page_token | string | Opaque continuation from a prior page. |
ListTeamRepoCredentialsResponse
ListTeamRepoCredentialsResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| credentials | TeamRepoCredential | repeated | Redacted credentials in this bounded page. |
| next_page_token | string | Opaque continuation, empty at the end. | |
| can_manage | bool | optional | Real L3 management gate for check/bind/unbind/revoke, not secret supply. Omission on an older server differs from denial; writes recheck the gate. |
| denial_reason | string | Verbatim denial from the actual server write authority. | |
| can_supply_secret | bool | optional | Real L4 gate for create/rotate; independent of L3 management authority. |
| secret_denial_reason | string | Verbatim create/rotate authority denial, absent when secret supply is allowed. |
PutRepoMapRequest
PutRepoMapRequest applies a generated map at a pinned commit.
| Field | Type | Label | Description |
|---|---|---|---|
| repo_id | string | The repository the map describes. | |
| generation_run_id | string | TK-8.5: the generation run id. Required. | |
| generated_commit | string | TK-8.3: the commit the governed checkout was pinned to. Required, and a full 40-hex sha — a branch name is not a pin. | |
| generated_ref | string | The ref that commit was taken from. Required. | |
| sections | GeneratedSection | repeated | The generated sections. |
PutRepoMapResponse
PutRepoMapResponse states what the regeneration DID.
applied/preserved are reported separately because a regeneration that rewrote everything and one that changed nothing must not look alike to the caller that ran it.
| Field | Type | Label | Description |
|---|---|---|---|
| map | RepoMap | The map after the apply. | |
| applied_sections | SectionKind | repeated | Sections whose bodies were replaced. |
| preserved_sections | SectionKind | repeated | Locked sections kept verbatim. |
| recorded_divergences | Divergence | repeated | One per preserved section whose generated body actually differed. |
RecordRepoHeadRequest
RecordRepoHeadRequest stores a branch-head observation.
| Field | Type | Label | Description |
|---|---|---|---|
| repo_id | string | The registry entry the observation belongs to. | |
| head_commit | string | The observed head commit sha. | |
| head_ref | string | The ref that head belongs to. REQUIRED whenever head_commit is set: an observation of nothing nameable is what let the marker attribute it to the map's ref. The schema makes the ref-less form unrepresentable. | |
| commits_behind | int32 | optional | How many commits behind_base_commit is behind that head, if measured. |
| behind_base_commit | string | optional | The commit the distance was measured from. Required whenever commits_behind is set. |
RecordRepoHeadResponse
RecordRepoHeadResponse carries the updated entry.
| Field | Type | Label | Description |
|---|---|---|---|
| repo | Repo | The repository with its new head observation. |
RegenerateRepoMapRequest
RegenerateRepoMapRequest requests a run, never supplies a producer identity.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team. | |
| repo_id | string | Registered repository, already bound through the governed connection. | |
| request_id | string | Caller UUID deduplication key, reused for a retry of this intent. |
RegenerateRepoMapResponse
RegenerateRepoMapResponse describes durable accepted intent, not completion.
| Field | Type | Label | Description |
|---|---|---|---|
| intent_id | string | Durable intent id. | |
| state | string | Current queued/capacity/admitted state. | |
| reason | string | Sanitized limiting condition when present. |
RegisterRepoRequest
RegisterRepoRequest registers one repository to a team.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | The team unit to register it to. | |
| gitlab_project_id | string | Upstream GitLab project id. | |
| path_with_namespace | string | Upstream path. | |
| default_branch | string | Default branch. | |
| primary_language | string | Primary language, if known. | |
| responsibility | string | REQUIRED one-line responsibility. | |
| links | RegisterRepoRequest.LinksEntry | repeated | Named links. |
| provider | RepoProvider | Omission retains the legacy GitLab/unknown-host byte-preserving contract. | |
| provider_host | string | New GitLab requires a host. GitHub owner/repo defaults to github.com. | |
| repository_url | string | Optional HTTPS location; must agree with supplied structured identity. |
RegisterRepoRequest.LinksEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
RegisterRepoResponse
RegisterRepoResponse carries the created registry entry.
| Field | Type | Label | Description |
|---|---|---|---|
| repo | Repo | The registered repository. |
Repo
Repo is a team registration, not upstream access verification.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | Registry row id. | |
| team_unit_id | string | The team unit this repository is registered to. | |
| gitlab_project_id | string | Upstream GitLab project id. | |
| path_with_namespace | string | Upstream path, e.g. "sre/incident-tooling". | |
| default_branch | string | Branch maps are generated from unless a map says otherwise. | |
| primary_language | string | Primary language, if known. | |
| responsibility | string | The one-line statement of what this repository is responsible for. | |
| links | Repo.LinksEntry | repeated | Named links (issues, docs, dashboards). |
| archived | bool | Whether the repository is archived upstream. | |
| registered_at | google.protobuf.Timestamp | When it was registered to this team. | |
| head | RepoHead | Last observed head; absent means never observed. | |
| has_map | bool | Whether a map exists for this repository. | |
| provider | RepoProvider | Declared provider. Historical rows are GitLab with unknown host. | |
| provider_host | string | Canonical host; empty means unknown, not gitlab.com. | |
| repository_url | string | Server-derived HTTPS location, absent when host is unknown; not access proof. | |
| source_access_state | string | Provider evidence is separate from registration; unknown is not denial. | |
| source_access_last_confirmed_at | google.protobuf.Timestamp | Last positive source-access observation; absent means never confirmed. | |
| map_withheld_reason | string | Persisted denial; the map remains retained but its bytes are withheld. | |
| map_withheld | bool | Authoritative read barrier, independent of has_map (which means existence). True may have an empty reason when source evidence was no longer retained. | |
| connection | RepoConnectionState | Authorized L3 connection projection; absent for lower-clearance registry readers. |
Repo.LinksEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
RepoConnectionState
RepoConnectionState reports source readiness independently of map generation. It carries no token, PEM, raw provider message or sampled source bytes.
| Field | Type | Label | Description |
|---|---|---|---|
| repo_id | string | Registered repository id scoped to the named team. | |
| credential_id | string | Exact isolated team credential id. | |
| status | string | Server-owned lifecycle state. | |
| source_access_state | string | Typed server evidence class, independent of generator readiness. | |
| reason | string | Sanitized server reason; no raw provider error body. | |
| binding_revision | int64 | Monotonic binding revision fencing older observations. | |
| checked_credential_epoch | int64 | Credential epoch used for the latest verified binding. | |
| access_last_confirmed_at | google.protobuf.Timestamp | Last positive exact-repository access verification, not a time lease. | |
| last_checked_at | google.protobuf.Timestamp | Last completed provider observation. | |
| next_check_at | google.protobuf.Timestamp | Next eligible bounded check after shared quota/backoff. | |
| not_visible_since | google.protobuf.Timestamp | First qualified not-visible observation, only when persisted. | |
| effective_discovery_interval_seconds | int32 | Actual cadence used for the two-observation loss rule. |
RepoHead
RepoHead is the last observed head of a repository's default branch.
Its ABSENCE is meaningful and is the Day-0 state: no observation has been made, so staleness is UNKNOWN. It is never inferred.
| Field | Type | Label | Description |
|---|---|---|---|
| commit | string | The observed commit sha. | |
| observed_at | google.protobuf.Timestamp | When it was observed. | |
| ref | string | The ref this observation is OF. Not decoration: a freshness observation is a fact about a (repository, ref) PAIR, and without it a marker rendered for a map generated from another branch names THAT branch beside this sha — well-formed and false. Staleness is UNKNOWN when it differs from the map's generated_ref, and the sha is withheld. | |
| commits_behind | int32 | optional | How many commits the map is behind this head. optional because 0 is a REAL answer ("level with head") that must not be confused with "not measured". |
| behind_base_commit | string | optional | The map commit commits_behind was measured FROM. A distance is a fact about a pair, so the base travels with the count; a count whose base is not the current map commit is not reported. |
RepoMap
RepoMap is a repository's agent-facing map.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | Map row id. | |
| repo_id | string | The repository it describes. | |
| path_with_namespace | string | Upstream path of that repository, so a map is legible on its own. | |
| generation_run_id | string | TK-8.5: the generation run that produced it. | |
| generated_commit | string | TK-8.5: the commit it was generated from. | |
| generated_ref | string | The ref that commit was taken from. | |
| generated_at | google.protobuf.Timestamp | When it was generated. | |
| sections | RepoMapSection | repeated | The sections, in rendering order. |
| staleness | Staleness | How current the map is. NEVER absent — see the file header. | |
| provider | RepoProvider | Identity from the resolved registry entry. | |
| provider_host | string | Canonical host from the registry; empty means unknown. | |
| rendered_markdown | string | Shared agent-facing representation, including access, coverage and C6. |
RepoMapGenerationRun
RepoMapGenerationRun is sanitized history, with real metering and pinned provenance.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | Durable generation-run id and virtual historical document reference. | |
| repo_id | string | Registered repository id. | |
| state | string | Running means a current lease; expired leases render stalled immediately. | |
| stage | string | Current or terminal producer stage. | |
| reason | string | Named failure or refusal; no source body/provider error dump. | |
| generated_commit | string | Immutable source commit; absent before resolution. | |
| generated_ref | string | Exact target ref resolved by this run. | |
| created_at | google.protobuf.Timestamp | Admission time, after actual capacity reservation. | |
| finished_at | google.protobuf.Timestamp | Terminal completion time, when available. | |
| wire_attempts | int32 | Actual total charged wire attempts. | |
| input_tokens | int64 | Actual reconciled input token consumption including cache classes. | |
| output_tokens | int64 | Actual reconciled output tokens. | |
| model_calls | int32 | Actual paid attempts including unknown/failed attempts. |
RepoMapGeneratorOptions
RepoMapGeneratorOptions contains explicit choices, never hidden budget defaults.
| Field | Type | Label | Description |
|---|---|---|---|
| endpoint_id | string | Approved endpoint resource; no URL or provider key is accepted here. | |
| model_id | string | Exact named-provider model id declared by that endpoint. | |
| model_provider | string | Named model provider disclosed alongside FastRouter when applicable. | |
| agent_clearance | int32 | Agent deployment clearance, validated by the real AgentService gate. | |
| budget_tokens | int64 | Explicit positive AGENT-grain token cap; billing windows derive from owner. | |
| automatic_interval_seconds | int64 | Explicit automatic cadence. Zero is unconfigured, never sixty minutes. | |
| automatic_daily_limit | int32 | Explicit automatic admissions per team UTC day. Manual uses the same money cap. | |
| baseline_version | string | Installed structural policy version the user has reviewed. | |
| confirm_baseline | bool | Explicit confirmation of the shipped policy, not an approval bypass. | |
| expected_rejected_binding_id | string | Explicit rejected binding to re-request through its owning service. |
RepoMapGeneratorState
RepoMapGeneratorState distinguishes partial setup from verified readiness.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team, scoped to the authenticated org. | |
| revision | int64 | Monotonic desired-configuration revision. | |
| agent_id | string | Actual registered service-agent id when that stage completed. | |
| binding_id | string | Actual owner binding id; never a fabricated generic approval id. | |
| state | string | Named current setup/readiness state. | |
| reason | string | Real owner denial or truthful missing dependency. | |
| dependency_resource_id | string | Resource requiring approval or repair, when supplied by its owner. | |
| last_checked_at | google.protobuf.Timestamp | Last completed owner-state observation; absent means never checked. | |
| next_check_at | google.protobuf.Timestamp | Scheduled independent owner-state recheck. | |
| generation_enabled | bool | False until the real production generation switch is activated. | |
| can_manage | bool | Derived by the exact same server gate that authorizes mutations. | |
| manage_denial_reason | string | Verbatim gate reason when mutation authority is absent. | |
| options | RepoMapGeneratorOptions | Saved explicit choices, preserved across reload. | |
| not_recently_checked | bool | True when owner state has not been checked within two setup intervals. | |
| setup_step_remaining | bool | True while an authenticated caller must advance remaining owner-write stages. |
RepoMapSection
RepoMapSection is one section of a map.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | Section row id; the handle SetRepoMapSectionLock takes. | |
| kind | SectionKind | Which section this is. | |
| body | string | The current text. | |
| locked | bool | Whether a regeneration must leave it verbatim. | |
| curator_kind | CuratorKind | How the current text is attributed. | |
| curator_run_id | string | Set when curator_kind is CURATOR_KIND_GENERATION_RUN. | |
| curator_member_id | string | Set when curator_kind is CURATOR_KIND_MEMBER. | |
| curated_at | google.protobuf.Timestamp | When the current text was written. | |
| open_divergences | Divergence | repeated | Unacknowledged divergences against this section. Populated on reads so a lock cannot become a way to stop being told. |
RevokeTeamRepoCredentialRequest
RevokeTeamRepoCredentialRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| credential_id | string | Exact isolated team credential id. | |
| expected_credential_epoch | int64 | Exact credential epoch observed by the caller; stale writes are refused. |
RevokeTeamRepoCredentialResponse
RevokeTeamRepoCredentialResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| credential | TeamRepoCredential | Redacted persisted credential metadata. |
RotateTeamRepoCredentialRequest
RotateTeamRepoCredentialRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| credential_id | string | Exact isolated team credential id. | |
| expected_credential_epoch | int64 | Exact credential epoch observed by the caller; stale writes are refused. | |
| secret | TeamRepoCredentialSecret | Write-only replacement credential material. |
RotateTeamRepoCredentialResponse
RotateTeamRepoCredentialResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| credential | TeamRepoCredential | Redacted persisted credential metadata. |
SetRepoMapSectionLockRequest
SetRepoMapSectionLockRequest curates one section.
| Field | Type | Label | Description |
|---|---|---|---|
| section_id | string | The section to curate. | |
| locked | bool | Whether a regeneration must leave it verbatim from here on. | |
| body | string | optional | Replacement text. Unset leaves the body unchanged; the lock still moves. |
| acknowledge_divergence_ids | string | repeated | Divergences the curator has seen and is retiring. A divergence is retired ONLY here — never by a regeneration. |
SetRepoMapSectionLockResponse
SetRepoMapSectionLockResponse carries the curated section.
| Field | Type | Label | Description |
|---|---|---|---|
| section | RepoMapSection | The section after curation, with any divergences still open. |
Staleness
Staleness is how current a map is, computed at READ time.
It is carried on RepoMap itself so that no surface returning a map can return it without this. See the file header for why that is the mechanism rather than a convention.
| Field | Type | Label | Description |
|---|---|---|---|
| state | StalenessState | The computed state. STALENESS_STATE_UNSPECIFIED is a server fault. | |
| map_commit | string | The commit the map was generated from. | |
| head_commit | string | The last observed head of ref. Empty when none has been observed, AND empty when the only observation is of a different ref — in that case there is no head of ref to report, and reporting another ref's would be the falsehood this field's emptiness prevents. | |
| ref | string | The ref the MAP was generated from — the subject of the marker sentence. | |
| observed_ref | string | The ref the observation is OF. Equal to ref in CURRENT and BEHIND (they are unreachable otherwise); different in the mismatch flavour of UNKNOWN, where naming both is what lets an agent tell "nobody looked" from "we looked at a different branch". | |
| commits_behind | int32 | optional | Commits behind, when measured against THIS map's commit. optional because 0 means "level", not "unmeasured". |
| head_observed_at | google.protobuf.Timestamp | When the head was observed. Absent when none has been. | |
| marker | string | The rendered one-line marker, produced by the same renderer the MCP tool uses. Always populated: it is the sentence an agent reads, and one spelling across both surfaces is what makes M12 checkable at either. |
TeamRepoCredential
TeamRepoCredential is always redacted. org_id comes from authentication and is deliberately not an input selector. Only github.com is supported in V1b.
| Field | Type | Label | Description |
|---|---|---|---|
| id | string | Opaque credential identifier. | |
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| provider | RepoProvider | Declared provider; V1b accepts GitHub only. | |
| provider_host | string | Canonical host; V1b accepts github.com only. | |
| label | string | Human-readable connection name. | |
| credential_kind | string | Stored kind: github_app or pat. | |
| masked_hint | string | Redacted hint only; never contains PEM or a complete token. | |
| status | string | Server-owned lifecycle state. | |
| credential_epoch | int64 | Monotonic epoch owned by the credential row. | |
| scope_unverified | bool | True for opaque PAT scope; never a down-scope claim. | |
| expires_at | google.protobuf.Timestamp | Declared credential expiry; omitted when no expiry is declared. | |
| created_at | google.protobuf.Timestamp | When the credential was created. | |
| updated_at | google.protobuf.Timestamp | When the persisted state last changed. | |
| app_id | string | Numeric App id; absent for PAT credentials. |
TeamRepoCredentialSecret
TeamRepoCredentialSecret carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| github_app | GitHubRepoAppSecret | Dedicated read-only App material. | |
| github_pat | GitHubRepoPATSecret | Selected-repository fine-grained PAT material. |
UnbindRepoCredentialRequest
UnbindRepoCredentialRequest carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| team_unit_id | string | Exact owning team; authenticated org is never accepted from the request. | |
| repo_id | string | Registered repository id scoped to the named team. | |
| expected_binding_revision | int64 | Exact binding revision observed by the caller; stale writes are refused. |
UnbindRepoCredentialResponse
UnbindRepoCredentialResponse carries the scoped connection operation contract.
| Field | Type | Label | Description |
|---|---|---|---|
| connection | RepoConnectionState | Persisted sanitized source-connection state. |
UpdateRepoRequest
UpdateRepoRequest edits a registry entry. Unset optional fields are left unchanged.
| Field | Type | Label | Description |
|---|---|---|---|
| repo_id | string | The registry entry to edit. | |
| responsibility | string | optional | New one-line responsibility. |
| default_branch | string | optional | New default branch. |
| primary_language | string | optional | New primary language. |
| links | UpdateRepoRequest.LinksEntry | repeated | Replacement link map (whole-map replace, not a merge). |
| replace_links | bool | Whether links above should be applied at all — an empty map is a valid "clear the links" instruction and cannot be distinguished from "unset". | |
| archived | bool | optional | Archive/unarchive. |
| removed_from_team | bool | optional | Remove from the team's registry (soft). An entry removed this way stops appearing in ListRepos and frees the (team, project) key for re-registration. |
UpdateRepoRequest.LinksEntry
| Field | Type | Label | Description |
|---|---|---|---|
| key | string | ||
| value | string |
UpdateRepoResponse
UpdateRepoResponse carries the updated entry.
| Field | Type | Label | Description |
|---|---|---|---|
| repo | Repo | The updated repository. |
CuratorKind
CuratorKind attributes a section's current text.
A generated section is attributed to its RUN, never to a person who did not write it — TK-8.5 requires the curator of each curated section, and naming a human for machine-written text would make the provenance column a lie.
| Name | Number | Description |
|---|---|---|
| CURATOR_KIND_UNSPECIFIED | 0 | Never valid on the wire. |
| CURATOR_KIND_GENERATION_RUN | 1 | Written by a map generation run. |
| CURATOR_KIND_MEMBER | 2 | Written or accepted by a team member. |
RepoProvider
Repo is one registered repository. RepoProvider is a declared upstream service; registration is not access proof.
| Name | Number | Description |
|---|---|---|
| REPO_PROVIDER_UNSPECIFIED | 0 | Legacy request mode; stored historical provider is GitLab. |
| REPO_PROVIDER_GITLAB | 1 | GitLab with a declared project ID. |
| REPO_PROVIDER_GITHUB | 2 | GitHub declared owner/repository location. |
SectionKind
SectionKind is the closed set of map sections (TK-8.2).
| Name | Number | Description |
|---|---|---|
| SECTION_KIND_UNSPECIFIED | 0 | Never valid on the wire. |
| SECTION_KIND_PURPOSE | 1 | What the repository is for. |
| SECTION_KIND_RESPONSIBILITIES | 2 | What it is responsible for. |
| SECTION_KIND_DIRECTORY_OWNERSHIP | 3 | The directory-ownership table: path -> owns -> touch-when. |
| SECTION_KIND_CONVENTIONS | 4 | Conventions a change is expected to follow. |
| SECTION_KIND_DO_NOT_TOUCH | 5 | Do-not-touch zones. |
| SECTION_KIND_RELATED_REPOSITORIES | 6 | Evidence-backed relationships to other repositories (founder D8). Schema support does not imply that relation extractors have run. |
StalenessState
StalenessState is how a map's pinned commit relates to the last observed head of the ref it was generated from.
There is NO valid unspecified state. The zero value exists because proto3 requires one and buf's ENUM_ZERO_VALUE_SUFFIX rule mandates the name; it is rejected by the server's response validation, so a map carrying it can never be serialised. That is M12 as a type rather than as a review checklist.
| Name | Number | Description |
|---|---|---|
| STALENESS_STATE_UNSPECIFIED | 0 | Never valid on the wire. A response carrying it is a server fault. |
| STALENESS_STATE_CURRENT | 1 | The map's commit IS the last observed head of its ref. |
| STALENESS_STATE_BEHIND | 2 | The map's commit is not the observed head: the repository has moved. |
| STALENESS_STATE_UNKNOWN | 3 | No head has been observed for this repository, so how current the map is CANNOT BE KNOWN. It is a distinct answer from CURRENT and must never be rendered as one — an unobserved repository is the Day-0 state. |
RepoConnectionService
RepoConnectionService manages isolated team source credentials. It is mounted on the authenticated Context Engine; it does not run a generator or expose stored secrets. Registration alone is never evidence of provider access.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| CreateTeamRepoCredential | CreateTeamRepoCredentialRequest | CreateTeamRepoCredentialResponse | CreateTeamRepoCredential creates a write-only GitHub team connection. |
| ListTeamRepoCredentials | ListTeamRepoCredentialsRequest | ListTeamRepoCredentialsResponse | ListTeamRepoCredentials returns paginated redacted metadata and the real server authority projection. It never decrypts a secret for display. |
| RotateTeamRepoCredential | RotateTeamRepoCredentialRequest | RotateTeamRepoCredentialResponse | RotateTeamRepoCredential replaces the secret at the exact current epoch, fences old work, and requires positive re-verification of each binding. Only active credentials rotate: revoked is terminal; create and bind a replacement. |
| RevokeTeamRepoCredential | RevokeTeamRepoCredentialRequest | RevokeTeamRepoCredentialResponse | RevokeTeamRepoCredential fences the epoch and withholds dependent maps immediately. Revocation is terminal; late probes cannot undo it. |
| CheckTeamRepoConnection | CheckTeamRepoConnectionRequest | CheckTeamRepoConnectionResponse | CheckTeamRepoConnection runs a bounded, deduplicated check of an existing binding through its credential's shared quota. It never rebinds silently. |
| BindRepoCredential | BindRepoCredentialRequest | BindRepoCredentialResponse | BindRepoCredential verifies the registered canonical repository using an exact team credential before committing its provider identity. App installation and repository IDs are derived, never supplied by a user. |
| UnbindRepoCredential | UnbindRepoCredentialRequest | UnbindRepoCredentialResponse | UnbindRepoCredential records an explicit human denial and fences in-flight checks. It does not revoke a credential shared by other repositories. |
RepoMapGenerationService
RepoMapGenerationService is the finite, tool-less Context Engine producer. These operations handle no source secret. Every write uses knowledge.manage and the registry's actual L3 gate; owner operations retain their own authority.
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| ConfigureRepoMapGenerator | ConfigureRepoMapGeneratorRequest | ConfigureRepoMapGeneratorResponse | ConfigureRepoMapGenerator advances resumable owner-service setup. It never approves bindings or endpoints. Repeating the same desired state is safe. |
| GetRepoMapGenerator | GetRepoMapGeneratorRequest | GetRepoMapGeneratorResponse | GetRepoMapGenerator returns actual persisted dependencies and check times. |
| RegenerateRepoMap | RegenerateRepoMapRequest | RegenerateRepoMapResponse | RegenerateRepoMap durably deduplicates a human request under the same caps. |
| ListRepoMapRuns | ListRepoMapRunsRequest | ListRepoMapRunsResponse | ListRepoMapRuns returns bounded sanitized history, never source excerpts. |
RepoService
RepoService is the management surface for the team repo registry and its curated maps. Every operation is tenant-scoped: the owning org and the acting member are taken from the request scope, never from the request body, and every statement carries an explicit org predicate on top of row-level security.
Authorization (mirroring KnowledgeService, handler_perms.go):
- reads (ListRepos, GetRepoMap) — knowledge.read
- writes (RegisterRepo, UpdateRepo, PutRepoMap, RecordRepoHead, SetRepoMapSectionLock) — knowledge.manage
| Method Name | Request Type | Response Type | Description |
|---|---|---|---|
| RegisterRepo | RegisterRepoRequest | RegisterRepoResponse | RegisterRepo adds a repository to a team's registry. The one-line responsibility is REQUIRED: a registry entry that cannot say what the repository is for does not satisfy TK-8.1, and F8 acceptance 1 would otherwise be dischargeable by an empty string. |
| ListRepos | ListReposRequest | ListReposResponse | ListRepos returns a team's registered repositories. Team-scoped: a repository registered to another team is not returned, whatever the caller's clearance. |
| UpdateRepo | UpdateRepoRequest | UpdateRepoResponse | UpdateRepo edits a registry entry. Every editable field is optional, so "leave unchanged" and "set to empty" are distinguishable — with a bare proto3 string they are the same wire value and a partial update silently clears whatever it did not mention. |
| RecordRepoHead | RecordRepoHeadRequest | RecordRepoHeadResponse | RecordRepoHead stores an observation of the head of ONE REF. It is the freshness WRITER: Phase 2's GitLab webhook calls it, and until then a repository with no observation renders staleness UNKNOWN rather than CURRENT. It never touches a map. |
head_ref is REQUIRED. An observation carries the ref it is OF, because staleness for a map generated from release/1.2 cannot be answered by an observation of main — and answering it anyway produced a confident falsehood in the rendered marker (R1 on PR #3090). |
| PutRepoMap | PutRepoMapRequest | PutRepoMapResponse | PutRepoMap applies a legacy/manual map at a pinned commit. It refuses an admitted governed run ID or replacement of a governed map; those writes require the server-owned RegenerateRepoMap producer.
LOCK SEMANTICS, both halves (TK-8.4): - an UNLOCKED section is replaced by the generated body; - a LOCKED section survives VERBATIM, and if the generated body differs the difference is recorded as a divergence.
A lock suppresses the EDIT, never the NOTIFICATION. Proving only the survival half would leave a lock that silences. | | GetRepoMap | GetRepoMapRequest | GetRepoMapResponse | GetRepoMap returns a repository's current map with its staleness computed at read time and the open divergences attached to the sections they concern. | | SetRepoMapSectionLock | SetRepoMapSectionLockRequest | SetRepoMapSectionLockResponse | SetRepoMapSectionLock is the curation surface: lock or unlock a section, optionally replace its body, and acknowledge divergences the curator has seen. Acknowledging is what retires a divergence — it is never retired by a regeneration, because that would let a lock stop the notification after all. |
Scalar Value Types
| .proto Type | Notes | C++ | Java | Python | Go | C# | PHP | Ruby |
|---|---|---|---|---|---|---|---|---|
| double | double | double | float | float64 | double | float | Float | |
| float | float | float | float | float32 | float | float | Float | |
| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| uint32 | Uses variable-length encoding. | uint32 | int | int/long | uint32 | uint | integer | Bignum or Fixnum (as required) |
| uint64 | Uses variable-length encoding. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum or Fixnum (as required) |
| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int | uint32 | uint | integer | Bignum or Fixnum (as required) |
| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long | uint64 | ulong | integer/string | Bignum |
| sfixed32 | Always four bytes. | int32 | int | int | int32 | int | integer | Bignum or Fixnum (as required) |
| sfixed64 | Always eight bytes. | int64 | long | int/long | int64 | long | integer/string | Bignum |
| bool | bool | boolean | boolean | bool | bool | boolean | TrueClass/FalseClass | |
| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode | string | string | string | String (UTF-8) |
| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str | []byte | ByteString | string | String (ASCII-8BIT) |