User Story
As an API maintainer, I want database storage messages separated from public RPC contracts, so that public API evolution and storage migration can be reviewed and versioned independently.
Problem Statement
Persistence decodes database payloads directly into protobuf messages, including types also returned by public RPCs. Several messages named Stored* live inside the public openshell.v1 package even though they are not used in RPC signatures. Generated clients and descriptor consumers therefore see storage-only types, while changes to shared public/persisted types also become database migrations.
Impact / Why This Matters
The beta compatibility promise would accidentally include internal storage messages. A public field cleanup can break stored data, and a storage-only change can appear to break the public package. Maintainers cannot reason about wire compatibility and durable-data compatibility as separate concerns.
Proposed Design
Move storage-only messages into an explicitly internal, versioned storage protobuf package and exclude them from public SDK exports where practical. For resource messages used both on the wire and in persistence, decide whether to introduce internal storage twins with explicit conversion at the persistence boundary.
If storage twins are deferred, document which public messages are also durable storage formats, permanently prohibit unsafe tag reuse, and require migration review for every change to those messages.
Acceptance Criteria
Alternatives Considered
Leave dual-purpose types in place and rely on field-number discipline. This is the lowest-cost option but permanently couples every API change to storage. Move only the pure Stored* messages. This is a useful first step and may be selected if storage twins are not justified before 0.1.0.
Agent Investigation
crates/openshell-server/src/persistence/mod.rs decodes stored payloads into protobuf messages. Multiple Stored* declarations remain in proto/openshell.proto, alongside resource messages used both for persistence and public responses.
Related: #2565. Source audit: https://gist.github.com/mrunalp/e80942c1544a0225ee588796a41ab30b.
User Story
As an API maintainer, I want database storage messages separated from public RPC contracts, so that public API evolution and storage migration can be reviewed and versioned independently.
Problem Statement
Persistence decodes database payloads directly into protobuf messages, including types also returned by public RPCs. Several messages named
Stored*live inside the publicopenshell.v1package even though they are not used in RPC signatures. Generated clients and descriptor consumers therefore see storage-only types, while changes to shared public/persisted types also become database migrations.Impact / Why This Matters
The beta compatibility promise would accidentally include internal storage messages. A public field cleanup can break stored data, and a storage-only change can appear to break the public package. Maintainers cannot reason about wire compatibility and durable-data compatibility as separate concerns.
Proposed Design
Move storage-only messages into an explicitly internal, versioned storage protobuf package and exclude them from public SDK exports where practical. For resource messages used both on the wire and in persistence, decide whether to introduce internal storage twins with explicit conversion at the persistence boundary.
If storage twins are deferred, document which public messages are also durable storage formats, permanently prohibit unsafe tag reuse, and require migration review for every change to those messages.
Acceptance Criteria
Stored*messages move out of public API packages without changing their durable wire encoding.Alternatives Considered
Leave dual-purpose types in place and rely on field-number discipline. This is the lowest-cost option but permanently couples every API change to storage. Move only the pure
Stored*messages. This is a useful first step and may be selected if storage twins are not justified before 0.1.0.Agent Investigation
crates/openshell-server/src/persistence/mod.rsdecodes stored payloads into protobuf messages. MultipleStored*declarations remain inproto/openshell.proto, alongside resource messages used both for persistence and public responses.Related: #2565. Source audit: https://gist.github.com/mrunalp/e80942c1544a0225ee588796a41ab30b.