An application outside the console cannot connect to it: there is no published protocol #171

Open
opened 2026-10-06 18:11:39 +00:00 by cgalo5758 · 3 comments
Owner

What a person cannot do today

Connect an application to the console without adding code to the console's repository. The console now stores what each application should hold, one desired-state record per connection and recipient with a generation that rises when the content changes, but nothing sends those records anywhere: there is no transport, no way for an application to register, and no specification to write a connector against.

What they should be able to do

Write a connector in any language against a published specification, register it with a deployment, and receive the desired state of every person and organization it serves.

  • The messages are defined in Protobuf and served through Connect, so one definition answers as JSON over HTTP (the required binding), gRPC and gRPC-Web. Field names on the wire are snake_case; OpenAPI and JSON Schema files are generated. The specification lives in a separate repository under Apache-2.0.
  • The console pushes records, and a connector may also pull them. Temporal stays inside the console; a connector does not import a Temporal SDK.
  • A connector announces a manifest. A deployment allowlists connector origins, with patterns such as *.example.org. Pairing uses a one-time code. Requests are signed in both directions with ed25519, naming the connection and the operation. A manifest change is staged until an operator approves it, and approvals are recorded.
  • The minimum connector declares a manifest, signs and verifies, applies desired state and answers the read-back. Every other capability is an optional class it declares; forget is required whenever it asks for personal data.
  • The read-back interval and the push timeout become operator settings on each connection, and the read-back page size is capped by a maximum the manifest declares.
  • An operator can cut a person off at every connection.
  • A numeric entry states "unlimited" explicitly rather than as -1 (#164).

Why it matters

A deployment must not have to fork the console to connect its application, and each application should need one connector instead of code on both sides. This is the first of four pieces of work that make up the integration contract, all due before launch; together they are estimated at about 45 developer-weeks at the midpoint, between 26 and 64.

Where

internal/integration (registration, the transport interface), internal/workflows/desiredstate (push and read-back exist but have no transport), a new specification repository, and the operator's connection pages.

Done when

A connector built only from the specification pairs with a deployment, receives signed pushes of its records, answers the read-back, and an operator can approve its manifest, suspend it and cut a person off from the console.

Order

Comes after #166 and #165.

## What a person cannot do today Connect an application to the console without adding code to the console's repository. The console now stores what each application should hold, one desired-state record per connection and recipient with a generation that rises when the content changes, but nothing sends those records anywhere: there is no transport, no way for an application to register, and no specification to write a connector against. ## What they should be able to do Write a connector in any language against a published specification, register it with a deployment, and receive the desired state of every person and organization it serves. - The messages are defined in Protobuf and served through Connect, so one definition answers as JSON over HTTP (the required binding), gRPC and gRPC-Web. Field names on the wire are snake_case; OpenAPI and JSON Schema files are generated. The specification lives in a separate repository under Apache-2.0. - The console pushes records, and a connector may also pull them. Temporal stays inside the console; a connector does not import a Temporal SDK. - A connector announces a manifest. A deployment allowlists connector origins, with patterns such as `*.example.org`. Pairing uses a one-time code. Requests are signed in both directions with ed25519, naming the connection and the operation. A manifest change is staged until an operator approves it, and approvals are recorded. - The minimum connector declares a manifest, signs and verifies, applies desired state and answers the read-back. Every other capability is an optional class it declares; forget is required whenever it asks for personal data. - The read-back interval and the push timeout become operator settings on each connection, and the read-back page size is capped by a maximum the manifest declares. - An operator can cut a person off at every connection. - A numeric entry states "unlimited" explicitly rather than as -1 (#164). ## Why it matters A deployment must not have to fork the console to connect its application, and each application should need one connector instead of code on both sides. This is the first of four pieces of work that make up the integration contract, all due before launch; together they are estimated at about 45 developer-weeks at the midpoint, between 26 and 64. ## Where `internal/integration` (registration, the transport interface), `internal/workflows/desiredstate` (push and read-back exist but have no transport), a new specification repository, and the operator's connection pages. ## Done when A connector built only from the specification pairs with a deployment, receives signed pushes of its records, answers the read-back, and an operator can approve its manifest, suspend it and cut a person off from the console. ## Order Comes after #166 and #165.
cgalo5758 added this to the Public launch milestone 2026-10-06 18:11:39 +00:00
cgalo5758 added the
kind
enhancement
area/integrations
labels 2026-10-06 18:11:39 +00:00
Author
Owner

Order: followed by #172, then #173, then #174.

Order: followed by #172, then #173, then #174.
Author
Owner

Before the protocol fixes the shape of a lifecycle request, it has to say whether one request can cover several instances. FedWiki's swap of the active site is the case today: it parks one site and activates another as two single-site requests held together by their workflow id (#184).

Before the protocol fixes the shape of a lifecycle request, it has to say whether one request can cover several instances. FedWiki's swap of the active site is the case today: it parks one site and activates another as two single-site requests held together by their workflow id (#184).
Author
Owner

Inbound messages need one rule for personal data, and the contract is the place to state it.

Today each part of the console decides for itself what it keeps from a message. The Discourse receiver stores every event body whole, so the email addresses of everyone who signs up on the forum, members or not, sit in core.webhook_events (#163). The Stripe receiver stores the body minus a list of key names it knows. Workflow inputs carry members' names and sign-in identifiers in plain text (#162), and an error message can carry a person's email into the logs. Each of these gets fixed one list at a time.

The contract's messages are defined in Protobuf, so the definition can say, field by field, which values are personal. Protobuf already has a field option for values that must not be printed (debug_redact, meant for credentials); a field option of the contract's own can mark personal data. Then:

  • whatever the console keeps of a message, whether an inbound event record, a workflow input, a log line or an error, is written from the definition, with marked fields left out or redacted, instead of from a list each integration keeps;
  • the manifest's statement of the personal data a connector asks for can be checked against the fields it uses, and forget, which this issue already requires whenever a connector asks for personal data, covers exactly those fields;
  • a connector's author reads in one place what the console treats as personal.

#163 fixes the Discourse receiver where it stands, keeping only the forum ids processing needs, and cleans the rows already stored. That receiver goes away with #174, so the general rule belongs here.

Inbound messages need one rule for personal data, and the contract is the place to state it. Today each part of the console decides for itself what it keeps from a message. The Discourse receiver stores every event body whole, so the email addresses of everyone who signs up on the forum, members or not, sit in `core.webhook_events` (#163). The Stripe receiver stores the body minus a list of key names it knows. Workflow inputs carry members' names and sign-in identifiers in plain text (#162), and an error message can carry a person's email into the logs. Each of these gets fixed one list at a time. The contract's messages are defined in Protobuf, so the definition can say, field by field, which values are personal. Protobuf already has a field option for values that must not be printed (`debug_redact`, meant for credentials); a field option of the contract's own can mark personal data. Then: - whatever the console keeps of a message, whether an inbound event record, a workflow input, a log line or an error, is written from the definition, with marked fields left out or redacted, instead of from a list each integration keeps; - the manifest's statement of the personal data a connector asks for can be checked against the fields it uses, and forget, which this issue already requires whenever a connector asks for personal data, covers exactly those fields; - a connector's author reads in one place what the console treats as personal. #163 fixes the Discourse receiver where it stands, keeping only the forum ids processing needs, and cleans the rows already stored. That receiver goes away with #174, so the general rule belongs here.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wiki-cafe/member-console#171