Skip to content

feat(billing): Add contract-owned retention override config#370

Draft
dashed wants to merge 1 commit into
aleal/feat/package-retention-defaultsfrom
aleal/feat/contract-retention-config
Draft

feat(billing): Add contract-owned retention override config#370
dashed wants to merge 1 commit into
aleal/feat/package-retention-defaultsfrom
aleal/feat/contract-retention-config

Conversation

@dashed

@dashed dashed commented Jul 17, 2026

Copy link
Copy Markdown
Member

Stacks on #369. Adds RetentionConfig as a fourth Contract component, carrying contract-owned retention overrides layered on top of the package retention defaults added in #369.

Shape

message RetentionOverride {
  DataCategory category = 1;                     // keyed by billing category, matching PackageConfig.retention_defaults
  optional StandardRetention standard = 2;       // absent -> inherit the package default's standard
  optional DownsampledRetention downsampled = 3; // absent -> inherit the package default's downsampled
}
message RetentionConfig {
  string revision = 1;                           // opaque; consumers must not parse
  optional StandardRetention organization = 2;   // org-wide scalar, legacy-compat, applies to every category
  repeated RetentionOverride overrides = 3;
}
// Contract { ...; RetentionConfig retention_config = 4; }

Semantics

  • An override is a sparse per-category patch, not a whole-policy replacement. standard and downsampled are independently optional; an absent field inherits the corresponding package default, and the two resolve as independent chains (a standard-only override keeps the package's downsampled).
  • Retention identity is the billing DataCategory, so package defaults and contract overrides always resolve against the same key.
  • organization is a single duration applied to standard and downsampled alike — a temporary mirror of the legacy scalar organization retention; per-category overrides are the forward-looking mechanism.
  • RetentionConfig is the raw stored input to effective-retention resolution, not the resolved policy. Nothing consumes it authoritatively yet.

Python and Rust round-trip coverage exercises sparse standard-only and downsampled-only overrides, the inherit-standard downsampled marker, an absent organization scalar, and embedding on Contract.

Add RetentionConfig as a fourth Contract component, carrying contract-owned
retention overrides layered on top of the package retention defaults. Each
override is a sparse per-category patch keyed by billing data category, with
standard and downsampled independently optional so an absent field inherits the
package default. RetentionConfig also carries an optional organization-wide
scalar for legacy compatibility.

RetentionConfig is the raw stored input to effective-retention resolution, not
the resolved policy itself. Python and Rust round-trip coverage exercises sparse
standard-only and downsampled-only overrides, the inherit-standard downsampled
marker, an absent organization scalar, and embedding on Contract.
@github-actions

Copy link
Copy Markdown

The latest Buf updates on your PR. Results from workflow ci / buf-checks (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed✅ passed✅ passed✅ passedJul 17, 2026, 11:30 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant