Proposal 026: Resource Opinions and Discussion Surfaces¶
Based on:
doc/project/20-memos/resource-opinions-and-discussion.mddoc/project/20-memos/reputation-signal-v1-invariants.mddoc/project/20-memos/orbiplex-whisper.md
Status¶
Accepted. P026-001–003 are implemented and runtime-qualified as of 2026-10-12: shared open-reference authoring, pair-only opinion reads and recoverable domain rebuild, with retained SQLite and Matrix evidence. Rich discussion surfaces and Agora P17 navigation remain future work; this qualification does not establish production readiness or cross-homeserver federation.
Date¶
2026-04-10
Executive Summary¶
Orbiplex has subject-oriented trust and signal concepts. This proposal defines the portable hard-MVP way for participants to express opinions about arbitrary resources such as:
- a URL,
- a product identified by EAN,
- a node,
- an organization in the swarm,
- a place identified by GPS coordinates,
- a future publication artifact,
- or another externally referenceable object.
This proposal introduces a small MVP artifact:
resource-opinion.v1
The key decisions are:
- a target resource is identified by the pair
resource/kindandresource/id, - the canonical derived key is
resource/kind + ":" + resource/id, - subject identity, authorship, and timing are carried by the
enclosing envelope (
agora-record.v1record/about[0],author/participant-id,authored/at);resource-opinion.v1itself is a content-body schema and does not duplicate those fields, - one opinion carries an optional
opinion/textand may addopinion/lang,opinion/tags, a five-pointopinion/ratingin1..5(with0or absence meaning no rating), and relational fields (opinion/in-reply-to,opinion/related,opinion/see-also); the schema is also open to kind-specific namespaced extensions such asrumor/credibilityandrumor/rejection-reason, - resource opinion artifacts remain distinct from participant or node reputation,
- a later discussion surface may attach to the same canonical resource key, but discussion threads and forum semantics are not part of the hard-MVP opinion artifact.
This keeps the core small:
- resource identity stays generic,
- opinion expression stays cheap,
- and richer discussion semantics can evolve later without forcing a large first schema.
Context and Problem Statement¶
Orbiplex already has concepts for:
- subject identity,
- reputation-like signals,
- social-signal exchange,
- and protocol-visible publication artifacts.
What is missing is a resource-facing review layer.
Without such a layer:
- opinions about external resources remain application-local,
- there is no shared contract for simple review or recommendation traces,
- and any future resource discussion feature would have to invent its own target identity model from scratch.
The target resource may be heterogeneous. For example:
url:https://example.org/articleean:5901234123457node:node:did:key:z6MkExampleNodeorg:org:did:key:z6MkExampleOrggps:51.107883,17.038538
The identity model therefore must stay generic and must not assume one global resource ontology.
Goals¶
- Define one minimal portable artifact for participant-authored resource opinions.
- Freeze the resource identity rule using
resource/kindandresource/id. - Allow both verbal and scalar expression.
- Reserve a clean extension path for attached resource discussion surfaces.
- Keep the semantics separate from reputation and sanctions.
Non-Goals¶
- This proposal does not define a final moderation model.
- This proposal does not define forum, channel, or threaded-comment schemas.
- This proposal does not define resource discovery, ranking, or recommendation algorithms.
- This proposal does not define one global registry of valid
resource/kindvalues. - This proposal does not define AI-agent delegation policy beyond preserving room for explicit authorship labeling in future discussion artifacts.
Decision¶
1. Resource Identity¶
Every opinion target MUST be identified by:
resource/kindresource/id
The canonical derived key is:
resource/key = resource/kind + ":" + resource/id
Rules:
resource/idMUST be treated as opaque within its kind,- consumers MUST split
resource/keyonly on the first:, - and no consumer may assume that
resource/idhas URI semantics unless the kind contract explicitly says so.
This is necessary because some ids, such as URLs, already contain :.
Common early resource kinds MAY include:
urleannodeorggps
For node and org, resource/id should use canonical protocol-visible
identifiers. For gps, resource/id stays opaque in this proposal; a later kind
contract should freeze coordinate order, precision, and privacy rules.
1.1. Country-scoped identifier namespaces¶
A resource kind MAY name a country-scoped identifier namespace, using a
lower-case ISO 3166-1 alpha-2 country code followed by an unambiguous scheme
name, separated by hyphens: <country>-<scheme>. Where a scheme name alone
is ambiguous, include the registry qualifier, for example pl-nil-pwz for
PWZ numbers in the Polish Central Register of Physicians and Dentists.
This is an Orbiplex naming convention, not a claim that the resulting slug
is an official external identifier-system code.
For example, the resource reference and its derived key are:
{
"resource/kind": "pl-nil-pwz",
"resource/id": "<pwz-number>"
}
pl-nil-pwz:<pwz-number>
<pwz-number> is a documentation placeholder, not an issued or
domain-validated number. The example establishes the namespace convention;
it does not claim an implemented registry lookup or PWZ validator.
The following invariants preserve the generic resource contract:
- The entire
resource/kindis the namespace key. Generic consumers MUST NOT infer authority or parse its hyphen-separated parts. Country qualifiers describe the identifier system's jurisdiction, not the holder's nationality, residence, or current location. - Kinds remain an open catalogue. Operators and communities MAY propose new kind contracts; this convention neither introduces a global allow-list nor requires country prefixes for existing or international kinds. Unknown kinds remain opaque under the generic contract, subject to ordinary admission and disclosure policy; they MUST NOT be silently mapped to a familiar namespace.
- A kind contract MUST identify the relevant scheme/registry, what its values identify (for example a person, licence, organization, or registry entry), canonicalization and validation rules, and any known reassignment or alias semantics. Official namespace URIs/OIDs MAY be documented for interoperability; these are mappings, not additional fields required in every resource reference.
- Values remain strings. Country- and registry-specific normalization, check
digits, and lookups belong to optional kind-specific validators or adapters,
not the generic schema, Agora index, or core. Merely adding a
countryfield cannot disambiguate the existing key, which uses only kind and id. - Identifier equality establishes a shared reference within that namespace, not verified identity across namespaces, current professional entitlement, reputation, or the truth of a claim. Identifying a person through a public register does not itself authorize disclosure or public aggregation.
The design follows the namespace/value separation of FHIR Identifier and the jurisdiction/list-code precedent in org-id.guide, without importing their complete data models or catalogues into the core.
1.2. References in opinions and gossip¶
An opinion about such a resource keeps the qualified pair in envelope
record/about[0]; no country field or identity copy is added to the content.
Public gossip (public-gossip.v1) MAY use the same pair in its optional
envelope record/about. Neither use changes the record's epistemic status.
When opinion/see-also or gossip/see-also refers directly to the same
resource, its compact representation is ["pl-nil-pwz", "<pwz-number>"]:
the tuple's first element carries the full namespace and the second carries
only its identifier, not the derived resource/key. Existing record/topic
reference kinds keep their own contracts. Each surface retains its existing
size bounds; both see-also fields limit an id to 512 characters, whereas
resource-ref.v1 allows 2048. A bridge MUST NOT truncate an identifier to fit.
An opinion evaluating a rumor still references the rumor record, as specified
by P013, rather than replacing that
target with the person or resource mentioned in it. opinion/subject-kind
remains an overlay-selection hint, not a substitute for the envelope reference.
2. resource-opinion.v1 as the MVP Artifact¶
The MVP artifact for a participant-authored opinion is the content body
of an agora-record.v1 envelope:
schema = "resource-opinion.v1"
2.1. Envelope vs content separation¶
When a resource opinion is published on the Agora substrate (the MVP
transport, see proposal 035 and requirements-014 FR-001/FR-002/FR-011),
identity, authorship, timing, subject reference, and the canonical
record identifier live in the envelope (agora-record.v1), not in
the content body:
| Concern | Where it lives |
|---|---|
| subject of the opinion | envelope record/about[0] = {resource/kind, resource/id} |
| authoring participant | envelope author/participant-id |
| authoring timestamp | envelope authored/at |
| canonical record identifier | envelope record/id (derived from canonical signed bytes) |
| signature | envelope signature |
| topic routing | envelope topic/key (conventionally ai.orbiplex.opinions/<resource-kind>) |
The envelope's content object, validated by resource-opinion.v1,
carries only the verbal and scalar expression of the opinion. This
keeps the substrate layer open on resource/kind (the envelope accepts
any value matching the resource-ref.v1 shape) while the opinion
content stays a small, portable shape independent of how identity is
routed.
2.2. Content-body fields¶
Recommended minimum fields of resource-opinion.v1:
schema- optional
opinion/text - optional
opinion/lang - optional
opinion/rating - optional
opinion/tags - optional
opinion/subject-kind - optional
opinion/in-reply-to - optional
opinion/related - optional
opinion/see-also
Ingest invariants (applied to the content body only):
opinion/text, when present, MUST be a non-empty string. An opinion MAY be text-less if it carries at least one ofopinion/rating,opinion/in-reply-to,opinion/related,opinion/see-also, or a kind-specific extension key (see §2.4).opinion/rating, when present, MUST be an integer in the range0..5. Values1..5encode a five-point scale where1is the weakest and5the strongest positive assessment. The value0is the explicit "no rating" marker and is semantically equivalent to the field being absent. Consumers MUST NOT silently rescale ratings to a different range or to a reputation signal.opinion/lang, when present, annotatesopinion/text.opinion/tags, when present, is an array of non-empty strings.opinion/subject-kind, when present, is a short string naming the kind of subject the opinion is about (e.g.rumor,url,gps-location,public-person,ean). It is a payload-level hint for selecting an overlay schema and does not replace enveloperecord/about.opinion/in-reply-to, when present, is therecord/idof another opinion the author is directly replying to. Consumers MUST tolerate dangling references.opinion/related, when present, is an array ofrecord/idvalues of other opinions this opinion relates to (prior takes, corroborating views, explicit contrasts). The relation is loose by design.opinion/see-also, when present, is an array of 2-element vectors[kind, id]pointing at other opinable objects (URLs, rumors, resources, identities). Unlikeopinion/related, entries are NOT restricted to opinions.
Invariants tied to envelope fields (enforced by the envelope
contract, not by resource-opinion.v1):
- envelope
record/aboutMUST contain at least one{resource/kind, resource/id}entry; the first entry is treated as the primary subject for indexing and aggregation - envelope
author/participant-idMUST identify the immediate authoring participant - consumers MUST NOT split
resource/keyderived from envelope fields on any:other than the first one
2.3. Standalone (non-envelope) usage¶
For archival exports, off-line snapshots, or bridges to systems that
do not carry the Agora envelope, a receiver MAY present the opinion as
a flat object that inlines the envelope-native fields (resource/kind,
resource/id, optional resource/key, author/participant-id,
authored/at, record/id) alongside the content body. That flat form
is a projection of the envelope plus content, not a second
authoritative schema; it does not gain fields that the envelope does
not already carry.
2.4. Kind-specific extensions¶
resource-opinion.v1 keeps additionalProperties: true. The core
schema is intentionally minimal; domain-specific fields live in
namespaced extension keys of the form <kind>/<field>, where
<kind> matches the opinion/subject-kind selector (when present)
or the kind of the primary entry in envelope record/about.
Rules:
- Any field not named under the
opinion/*namespace MUST carry a<kind>/<field>shape. Flat unprefixed extension keys are reserved for the core and MUST NOT be introduced by extensions. - Namespaces are flat strings (no nested
<kind>/<sub>/<field>shapes). Multiple kinds MAY coexist on one opinion, but this is discouraged; the canonical pattern is oneopinion/subject-kindplus one matching namespace. - Validation of extension keys is performed by an overlay
schema registered separately from the core (e.g.
rumor-opinion.overlay.v1). The overlay validates only its own namespace; it does not redefineopinion/*fields. Consumers without the overlay installed MUST still accept the envelope — unknown namespaced keys are forward-compatible. - Overlays MUST NOT change the meaning of any
opinion/*field. In particular,opinion/ratingalways carries the five-point meaning defined in §2.2 regardless of kind. Kind-specific rating dimensions (e.g.rumor/credibility) live in the overlay namespace.
Concrete overlay defined as part of this proposal family:
-
rumor-opinion.overlay.v1— used whenopinion/subject-kindequalsrumor. Fields: -
rumor/credibility— integer1..5(optional). Orthogonal toopinion/rating; encodes an operator's assessment of how credible the rumor appears.0or absence means no credibility score. rumor/rejection-reason— closed enum (optional). Recognized values:spam,policy-violation,off-topic,abusive,duplicate,fabricated. The presence of any value is a suppression signal for the node's outbound propagation policy (proposal 013 §Operator-mediated rumor curation).
Further overlays (e.g. url-opinion.overlay.v1,
public-person-opinion.overlay.v1, gps-location-opinion.overlay.v1)
may be added as separate artifacts without touching the core.
3. Verbal, Scalar, and Relational Opinion Are All First-Class¶
An opinion MAY be:
- verbal only (text + language),
- rating only (no text, just
opinion/rating), - relational only (no text, just
opinion/in-reply-to,opinion/related, oropinion/see-also), - kind-specific only (no text, just overlay fields such as
rumor/rejection-reason), - or any combination of the above.
This avoids splitting the first schema into separate text-review, star-rating, and link-only artifacts while still allowing minimal use cases such as:
- "I only want to rate this item 4/5",
- "I only want to leave a comment in Polish",
- "I want to mark this rumor as spam without writing anything",
- "I want both a text and a rating, plus a pointer to a related earlier opinion".
4. Resource Opinion Is Not Reputation¶
resource-opinion.v1 MUST remain semantically separate from:
reputation-signal.v1,- participant assurance,
- sanctions,
- or governance incident records.
The distinction is:
- resource opinion attaches to an external or internal resource,
- reputation attaches to a subject such as a participant, node, org, or nym.
When resource/kind is node or org, the target is subject-addressable, but
the artifact is still an opinion about a resource view, not a
reputation-signal.v1. Consumers MUST NOT silently translate resource ratings
into subject reputation.
If a federation wants node or org opinions to affect reputation, it needs an explicit policy and a separate reputation artifact or validation path.
5. Discussion Surface Is a Later Attached Layer¶
Future discussion surfaces may attach to the same resource identity through one separate artifact family or registry entry, for example:
resource/channel-link.v1resource-forum-thread.v1
Those are placeholders only. This proposal freezes only the layering rule:
- resource identity is the stable base,
- opinions are one append-only expression layer over that base,
- richer discussion media may attach later without replacing the opinion artifact.
Recommended Example¶
A resource opinion as it travels through the Agora substrate — one
agora-record.v1 envelope carrying a resource-opinion.v1 content
body. The envelope holds identity and routing; the content body holds
the opinion itself.
{
"schema": "agora-record.v1",
"record/id": "sha256:4b7c9fzkMyAL8GBfQExampleRecordId00000000000000",
"record/kind": "opinion",
"topic/key": "ai.orbiplex.opinions/url",
"record/about": [
{
"resource/kind": "url",
"resource/id": "https://example.org/article"
}
],
"author/participant-id": "participant:did:key:z6MkExample",
"authored/at": "2026-04-10T08:15:00Z",
"content/schema": "resource-opinion.v1",
"content": {
"schema": "resource-opinion.v1",
"opinion/text": "Useful overview, but the sourcing is thin in the final section.",
"opinion/lang": "en",
"opinion/rating": 3
},
"signature": {
"alg": "ed25519",
"value": "sig_example_opinion_url_article_0001"
}
}
The same opinion published about a non-URL subject reuses the same
content body shape and swaps only the envelope's record/about[0] and
topic/key:
{
"schema": "agora-record.v1",
"record/kind": "opinion",
"topic/key": "ai.orbiplex.opinions/ean",
"record/about": [
{ "resource/kind": "ean", "resource/id": "5901234123457" }
],
"content/schema": "resource-opinion.v1",
"content": {
"schema": "resource-opinion.v1",
"opinion/text": "Solid packaging, product matched the description.",
"opinion/rating": 4
}
}
This illustrates why substrate layers (ingest, query, subject-index,
topic ACL) stay open on resource/kind: a new kind adds no new
content-body schema and no new relay surface.
MVP Read-Model Consequences¶
The minimum read-models implied by this proposal are:
- list opinions by exact
resource/key, resolved from the envelope'srecord/about[0], - list opinions by envelope
author/participant-id, - compute simple aggregates such as opinion count and average rating where ratings exist.
All three read-models are built over envelope fields plus the
resource-opinion.v1 content body; no read-model reads identity out
of the content body.
Hard-MVP consumers SHOULD tolerate:
- resources with no ratings and text only,
- resources with ratings and no text,
- multiple opinions over time from the same author when
supersedesis not yet enforced by policy.
Implementation Recommendations¶
Follow node:DEV-GUIDELINES.md: reuse the existing resource pair, signing and
admission boundaries, and replay-fed projections. This continuation closes
consumer gaps; it does not introduce another identifier protocol, a country
registry in the core, or a prerequisite NIL lookup.
Reuse and Consumer Boundaries¶
Consumer review on 2026-10-10 found these remaining seams:
node:agora-core/src/envelope.rsalready ownsResourceRef;node:agora-relay-trait/src/subject_index.rsindexes the full opaque pair. Reuse these rather than adding a country-aware identity type.node:agora-ui/src/agora.rsalready has subject lookup and an opinion builder with separate kind/id values, but its opinion form forcesurl; the generic compose builder does not populate enveloperecord/about.node:agora-projections/src/lib.rscurrently derives the opinionresource_keyas a digest of the pair, andnode:agora-service/src/main.rsqueries that stored key directly. This is a consumer mismatch with §1, not a replacement for the acceptedkind:idcontract.- Public gossip retains
gossip/see-alsoin its content, but does not project those links as opinions do. The separate owner is Agora backlog P17; it is not a dependency of basic resource publication or subject lookup.
These are code-level findings, not a claim of retained runtime acceptance. Implementation evidence and detailed migration notes belong in Node.
Small Data Shapes, Shared Conversions¶
Keep the following shapes distinct; they are bindings of existing contracts, not new wire schemas:
| Surface | Shape | Rule |
|---|---|---|
| Resource value | {"resource/kind": "pl-nil-pwz", "resource/id": "<pwz-number>"} |
Reuse ResourceRef; kind remains open, id remains a string. |
| Primary opinion subject | record/about[0] = ResourceRef |
Required for an opinion; later entries must not reorder or replace the primary subject. |
| Generic compose subjects | record/about = [ResourceRef, ...] |
Optional for record families that do not require a subject, including public gossip. |
| Related reference | [kind, id] in opinion/see-also or gossip/see-also |
Preserve the complete namespace and id; do not substitute the derived key for the second element. |
| Public derived key | kind + ":" + id |
Split on the first colon only; if supplied alongside the pair, reject disagreement. |
Use a shared UI resource editor with separate kind/id inputs and a convenient
URL mode. URL mode selects kind = url; generic mode must not run a URL parser
or require a registered validator. Namespace suggestions are optional, not an
allow-list. Preserve leading zeroes, case, punctuation and embedded colons in
opaque ids; no numeric coercion or silent trimming/normalization. Kind-specific
normalization belongs to an explicitly selected kind contract, not the generic
editor or relay. Escape displayed values and percent-encode each local route
segment; an unfamiliar id is not an automatically navigable external URL.
Both forms should map their local draft fields into the existing envelope
builder before signing. Do not place record/about inside content, infer it
from see-also, or replace an opinion's rumor-record target with a person
mentioned by that rumor. Reuse the existing signer/unlock flow and admission
policy; client validation does not replace Schema Gate at protocol boundaries.
Apply each receiving field's limits explicitly (including the 512-character
see-also id limit versus 2048 in resource-ref.v1); reject oversize input with
a field diagnostic rather than truncate it or partially publish it.
Implement pair-to-key, key-to-pair and pair-to-tuple conversions once as pure
operations at the lowest existing shared owner. Do not create a new service or
crate merely for these helpers. Test decode(encode(pair)) = pair, including
ids containing colons, and keep each carrier's validation at its boundary.
Projection-Key Compatibility and Recovery¶
The authoritative lookup is the exact pair, with case-sensitive (BINARY)
comparison. The public agora-projections.opinions.v2 DTO exposes
subject/kind, subject/id, and a derived subject/key. subject/key
presents the conceptual §1 resource/key; it avoids confusing that identity
with middleware effects[].resource/key, which has an independent contract.
No digest or derived key is authoritative or stored for new opinion rows.
Decision (2026-10-12): opinion queries accept only resource_kind and
resource_id, each exactly once. The old resource_key and resource-key
parameter names always return HTTP 400 legacy-digest-parameter-removed, for
any value and even alongside a valid pair. A legacy sha256:<digest> is itself
a valid open reference; heuristic value detection or reserving sha256 would
break open namespaces. The inventoried in-tree consumer is Agora service; it
changes together with the projection API. HATEOAS uses the full pair.
Migration creates a (resource_kind, resource_id, authored_at, record_id)
index. The obsolete resource_key NOT NULL column remains readable only to
old software: existing values stay intact and new rows write an empty value.
Current readers never consult it. Signed source records, their ids and
signatures remain unchanged.
Follow S028 Temporal Storage Convention
for the separate operator replay rebuild mode (default incremental, initially
only the opinions domain). Stage opinions, tags, links and indexed current
subject blocks together, persist
source cursors, catch up concurrent ingest and swap the domain atomically.
Network reads and verification run outside write transactions. Missing/pruned
source or interrupted work preserves the active projection and reports
incomplete reconstruction. Failures attributable to a pair degrade only that
pair; unassignable failures explicitly report unknown completeness. Incremental
replay and rebuild use the same projection decision: malformed retained records
are diagnosed as rejected and advance the source cursor. Missing source is a
different failure and still preserves the active projection. Current subject
blocks are indexed state; the diagnostic journal is not scanned on each read.
Topic read admission precedes the visible result limit. A bounded scan returns
complete and a pair-bound next_cursor, including a partial empty page when
the scan budget is exhausted. UI continuation uses the full pair. Reference
errors expose typed field and kebab-case reason values.
Authoring and Historical References¶
Pure ResourceRef conversions preserve the pair and split a key on the first colon. Validation is a separate operation: new builders, signing endpoints and queries enforce slug kind, 1–2048 Unicode code points (at most 8192 UTF-8 bytes), ECMA-262 whitespace boundaries, no control characters and NFC. NFC uses the same definition as signature canonicalization. Do not normalize opaque ids or reject every format/bidi character. Display accepted format characters with visible code-point markers and direction isolation.
The creation-only Agora authoring profile
limits new record/about arrays to eight unique references. Existing signed
v1 envelopes do not inherit this stricter profile. Ingress, indexing and replay
retain admitted history and record warnings in projection diagnostics. A
historical non-NFC id retains its original pair and record-id readback; a strict
query for that invalid pair returns 400. Carrier-specific constraints remain
local, including see-also's 512-character id limit.
New publication has a shared 48 KiB JSON-envelope budget, including the
signature and relay metadata. Check an estimate before signing and the actual
signed envelope before publication, with field/envelope diagnostics and no
truncation. This leaves a conservative allowance within Matrix's 64 KiB full
PDU limit; real Matrix acceptance must confirm it. Query + decodes to a space,
%2B to a plus; path + is literal. One URI encoder emits only unreserved
characters literally. A 32 KiB request-line allowance is local to subject and
opinion reads; other routes retain 8 KiB.
The shared no-JavaScript editor keeps drafts in form fields. CSRF-protected preview POST intents add, remove and reorder rows without signing. Opinion row zero is explicitly the main subject. The preview freezes author, timestamp, exact document and digest; editing requires another preview, and 423/unlock retries preserve that document. Subject UI combines opinion projection reads with public gossip from the relay subject index, deduplicating record ids and showing source diagnostics. This does not implement P17 related-link navigation.
Acceptance Boundary¶
Publication transport is a separate planned continuation owned by
P035-001–003:
compose/opinion/comment producers sign through the existing host and hand exact
records to AD's Agora adapter. Preserve record/about, open resource namespaces,
topic authority and record ids; expose queued versus relay-accepted publication.
Do not introduce an opinion-specific sender or retry queue. P026-001–003 remain
independently closable on the existing publication path; after migration, rerun
their consumer assertions through AD rather than claiming old evidence proves
the new path.
Use synthetic fixtures for pl-nil-pwz and an unregistered namespace, two kinds
sharing an identical id, an id with leading zeroes, and an id containing colons
and URL-sensitive characters. No live professional register or real-person
opinion is needed. A new kind must work without a code or allow-list change.
Retain evidence for both UI builders and the ordinary sign → publish → subject
query → projection query → UI read path, then repeat reads after restart/replay.
Include public gossip on its accepted public-signals topic, keeping its
epistemic status unchanged. Separately exercise see-also shape preservation;
gossip link navigation is qualified only by Agora P17, not this basic slice.
Negative cases include missing opinion subject, removed digest parameter names,
missing or duplicate pair components,
malformed/oversize references, denied publication and escaped malicious display
text. Unknown namespaces alone are not a refusal reason under generic shape
validation; ordinary admission and disclosure policy still apply.
Schema fixtures and unit tests alone do not close the UI/runtime gate. Record the tested revisions, commands, runtime/backend scope and retained report in Node; reconcile its implementation ledger and any affected MVP claims when the implementation lands, rather than marking them complete from this plan.
Implementation Tracker¶
This tracker covers the consumer continuation, not a retrospective inventory of
the already implemented substrate. Statuses are todo, partial, done and
blocked; done requires the stated gate and linked Node evidence.
| ID | Task | Status | Dependencies | Completion gate |
|---|---|---|---|---|
| P026-001 | Generic resource authoring in opinion and compose UI | done | Existing Agora signer and subject-index baseline | Both forms reuse a kind/id editor and populate envelope record/about; URL convenience remains; an unknown kind works without registration; opaque ids, field limits, escaping and denied-publication tests pass. |
| P026-002 | Canonical public opinion keys and legacy projection migration | done | §1 identity contract; S028 | Shared conversions preserve kind:id; queries use the exact pair; removed digest parameter names are rejected; the obsolete column is never read; domain rebuild and consumer changes are documented; interrupted rebuild, replay equivalence and incomplete-source diagnostics are tested without rewriting signed records. |
| P026-003 | Open-namespace consumer acceptance | done | P026-001, P026-002 | Retained UI and runtime evidence covers the Acceptance Boundary matrix for opinions and public gossip, including two namespaces with the same id, restart/replay and refusal paths; report scope distinguishes basic references from Agora P17 link navigation; relevant Node ledger/MVP evidence is reconciled. |
Qualified checkpoint (2026-10-12): node:docs/evidence/open-references/README.md
retains the existing story-008.smoke-result.v1 profile, its qualifier and
per-case process/HTTP artifacts: 20 SQLite and 18 Matrix runtime cases plus
separate conformance processes. Matrix B builds the subject index from inbound
/sync before projecting opinions, then repeats UI/API reads after restart and
replay. Signed non-NFC history is retained exactly and diagnosed. Both backends
publish a 49,134-byte envelope under the 48 KiB budget and refuse oversize
creation. Node ledger and Story-008 MVP entries record this consumer scope.
Matrix uses distinct clients on one homeserver; this proves distribution, not
federation. Matrix gossip is qualified only for integer JSON numbers;
the retained fixture has confidence=1. Ordinary fractional confidence, such
as 0.5, remains unqualified. This is a transport-contract mismatch: Matrix
canonical JSON permits integers only, in [-(2^53)+1, (2^53)-1]. Conduit v0.7.0
exposed it as HTTP 500 (IntConvert); that response is an observation, not the
cause of the restriction. Matrix canonical JSON
P035-004 owns the opaque-carrier replacement and its encoded PDU budget. Closing these three rows does not qualify general decimal-valued gossip, other P026 surfaces or production readiness. The original process artifacts and revisions remain frozen; the qualification report and evidence index carry this scope correction.
Review corrections (2026-10-12): live projection, incremental replay and domain
rebuild share opinion rejection decisions and diagnostics. Content rejection
advances the staged source cursor; source loss remains an incomplete rebuild.
Current pair blocks live in an indexed opinion_subject_blocks read model,
separate from the append-only journal, and are replaced with the staged domain.
Read admission precedes the visible result limit through bounded page scanning;
complete and a pair-bound next_cursor distinguish exhaustion from unfinished
work. DTO subject fields use subject/kind, subject/id, subject/key. Review
hashes use JCS without string normalization. Recent historical diagnostics link
to record-id retrieval without relaxing strict pair queries.
The retained node:docs/evidence/open-references/2026-10-12-review/qualification.json
qualifies these corrections with 20 SQLite and 18 Matrix runtime cases and
453 conformance tests per backend. Runtime source revisions are Node 9f114aae
and Orbidocs 308e936; the evidence index explains rejected-history, visibility
and materialized-block observations. General decimal gossip is still unqualified.
Pruned-source continuation¶
| ID | Task | Status | Dependencies | Completion gate |
|---|---|---|---|---|
| P026-004 | Explicit carry-forward for pruned opinion sources | todo | P026-002; S028 | Keep strict rebuild as the default. An explicit carry-forward mode retains prior opinion/tag/link/block rows only where source loss is proven; record prior projection revision, source bounds and per-record inherited provenance. Reports distinguish recomputed from inherited rows, preserve earlier blocks and unknown completeness, and never claim full-source replay equivalence. Restart, concurrent ingest, source-loss and future-format fixtures qualify the mode before status promotion. |
P026-001 and P026-002 may proceed independently against the existing pair contract; P026-003 closes their joint slice. Public-gossip related-link indexing and navigation remain the single-source task Agora P17, which can proceed independently and must not block basic open-namespace support.
Open Questions¶
No unresolved questions remain for this proposal slice. The decisions below record the approved defaults.
Resolved 2026-07-05:
resource/kindremains open. Individual kind contracts may gain dedicated validation when interoperability or safety requires it; this does not close the generic namespace catalogue (see §1.1).nodeandorgresource opinions require explicit anti-harassment, appeal, or moderation rules before they appear in public aggregates.gpsresources use a precision-bounded location key. Rawlat,lonis not the default public resource identifier.- One author has at most one active opinion per resource. Revisions are
append-only and linked through
supersedes. - Text and rating stay in one artifact family for v1. They may split later if their moderation policies diverge.
- The first attached discussion medium is an archival forum/thread reference, not an ephemeral chat-like channel.
- Future discussion artifacts mark human-authored versus agent-authored contributions through explicit authorship/origin flags reusing the P004/P011 provenance pattern.
Consequences¶
Positive:
- one small portable contract for resource review,
- clean separation from reputation,
- generic identity model reusable across many resource classes,
- envelope-vs-content layering keeps
resource-opinion.v1content-body shape independent of how identity, authorship, and routing are carried, so the same content schema works across Agora relays, archival exports, and future transports, - and a clear extension seam for later discussion surfaces.
Tradeoffs:
resource/kindremains open and individual kind contracts may require later normalization work,- the proposal intentionally leaves moderation and deduplication unresolved,
resource/keyis derived rather than authoritative, so consumers must validate it instead of trusting it blindly,- and implementers must remember that subject identity is not in
the content body — any tool that reads opinions must read from the
envelope's
record/about[0], not fromresource-opinion.v1fields, which intentionally no longer carry them.
Follow-Up¶
The immediate consumer slice is P026-001 and P026-002 followed by P026-003. The broader follow-up list below includes existing artifacts and later work; it is not evidence that the new consumer tasks are complete:
- one schema for
resource-opinion.v1, - one requirements note for normalization and revision policy,
- optionally one separate proposal for attached resource forum or channel semantics,
- proposal 040 (custodial redelivery and tombstones) covers how opinions survive relay data loss and how participants place copies with other nodes under capability-passport-backed custody; opinion-specific retention or right-to-forget flows build on that substrate.
- Keep kind-specific validation and alias lifecycle rules explicit without
turning the open
resource/kindcatalogue into a closed core enum. Country- scoped namespaces follow §1.1; validators remain outside the generic core. - Add moderation prerequisites for
resource/kind = nodeandresource/kind = org: explicit anti-harassment, appeal, or moderation rules must exist before public aggregates are exposed. - Specify the precision-bounded GPS key contract for
resource/kind = gps; rawlat,lonis not the default public resource identifier. - Document one-active-opinion-per-author semantics: revisions are append-only,
linked through
supersedes, and projected as the latest active opinion plus append-only history. - Reaffirm v1 unification:
opinion/textandopinion/ratingremain in one artifact family unless moderation policies later diverge. - Require future forum/thread/channel discussion artifacts to mark human-authored versus agent-authored contributions through explicit authorship/origin flags, reusing the P004/P011 provenance pattern.