Skip to content

feat(platform): D2: spec deployment-scoped artefacts - #529

Open
dannash100 wants to merge 5 commits into
mainfrom
feature/deployment-artefacts
Open

feat(platform): D2: spec deployment-scoped artefacts#529
dannash100 wants to merge 5 commits into
mainfrom
feature/deployment-artefacts

Conversation

@dannash100

Copy link
Copy Markdown
Contributor

Spec only, proposed.

Some artefacts are derived from one deployment's data and are wrong for anyone else; today every artefact is fleet-wide and the artefact reads are unauthenticated.

  • An artefact may belong to a group, resolved by type, platform and group together, and offered only where the caller's group is known.
  • Group-scoped artefacts rest in the group's own storage, are read back through Canopy with the digest verified, and their existence is not disclosed to anyone else.
  • Registration names the group and needs authorisation for it; a releaser credential registers unscoped artefacts only.

Base for #525.

@dannash100 dannash100 changed the title feat(platform): spec deployment-scoped artefacts feat(platform): D2: spec deployment-scoped artefacts Sep 3, 2026

@passcod passcod left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good in thrust, i have notes tho

Comment thread .workhorse/specs/platform/artifacts.md Outdated
An artefact may belong to a group, and one that does is offered only to that group.
An artefact belonging to no group is offered to every group, which is what a version's installers, migrations, and manifests are: properties of the version and of nothing narrower.

Belonging to a group is therefore an addition rather than a requirement, and the artefacts published today are unaffected.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this specifies "in time" which is disallowed by spec styleguide: it is true in our today but as soon as this ships makes no sense, since a reader in the future will already have "artefacts that belong to a group" in their today

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point

Comment thread .workhorse/specs/platform/artifacts.md Outdated
id: ART
---

# Version artefacts

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file's filename and i believe the code spells it "artifact" so we probably should keep to that in the spec

Comment thread .workhorse/specs/platform/artifacts.md Outdated
An artefact belonging to no group is offered to every group, which is what a version's installers, migrations, and manifests are: properties of the version and of nothing narrower.

Belonging to a group is therefore an addition rather than a requirement, and the artefacts published today are unaffected.
Resolution keys on type, platform, and group together, so a group-scoped artefact and an unscoped one of the same type do not displace each other and each group is offered its own.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads like an ungrouped viewer will query (version, type, platform) and see zero or one answer, and a grouped viewed will query (version, type, platform) and potentially see multiple answers?

Comment thread .workhorse/specs/platform/artifacts.md Outdated
A group-scoped artefact's existence is disclosed only to a caller it is offered to: a caller that names or guesses one it is not offered is answered as though it did not exist, so which groups hold one is not enumerable through the artefact surface.

A group scope exists because some artefacts are derived from a group's own data and are wrong for anyone else, a reporting schema being the case that motivates it (see [RPT](../public-server/reporting-schemas.md)).
Such an artefact is published into that group's own object storage, over a credential Canopy issues the publisher for the run, and is read back through Canopy, which passes it only to a caller the artefact is offered to.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a group's own object storage? This might be over- or under-specified: if this is introducing a new way to refer to objects (e.g. s3:// URLs, exclusively proxied) then this is underspecified, a new concept not introduced before, with no information in the spec about how auth to the object backend is done; if this is talking about the usual mechanism of an HTTP URL, then there's no guarantee that the URL is pointing to object storage only for the group, and putting it into this spec is over-reaching).

Comment thread .workhorse/specs/platform/artifacts.md Outdated

## Registration

A releaser device registers artefacts against a version over its own credential, which is what a product's release automation uses when it publishes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of "which is what {existing thing} does {when/for}" phrasing; in this one example and elsewhere in this draft. This again documents things that happen to be true today, but may not be in the future, so it's ambiguous whether the spec is over-reaching (specifying things that are not its business) or under-specified (defining hard requirements only by happenstance examples).

Comment thread .workhorse/specs/platform/artifacts.md Outdated
## Registration

A releaser device registers artefacts against a version over its own credential, which is what a product's release automation uses when it publishes.
Registering a group-scoped artefact requires being authorised for that group, and the group is named on the registration rather than inferred from the caller.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means we'd need N releaser devices for N groups?

Comment thread .workhorse/specs/platform/artifacts.md Outdated

A releaser device registers artefacts against a version over its own credential, which is what a product's release automation uses when it publishes.
Registering a group-scoped artefact requires being authorised for that group, and the group is named on the registration rather than inferred from the caller.
A restore consumer registers the artefacts its builds produce for the groups its own declarations authorise it to read, so a build needs no releaser credential to publish what it made.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That feels like a significant capability to be buried here, and also like something that should probably be gated to only some restores / restore-consumers. For our practical purposes, PGRO would be allowed, and only for those workflows that need it (ie the ones producing artifacts), but "someone restoring a backup" should not be.

Further, very slight over-reach in that this is naming "its builds" where one could plausibly imagine such a process wanting to register an artifact that isn't technically something it built.

Comment thread .workhorse/specs/platform/artifacts.md Outdated
An operator may also record one directly.
Canopy records which device registered an artefact and, where the registration names one, the run that produced it, so an artefact that arrived by automation is distinguishable from one entered by hand and traceable to what made it.

## What Canopy does not know

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and the "out of scope" section is running afoul of a pretty subtle spec-writing principle and should be carefully reconsidered: "documenting absences" vs "documenting anti-requirements". That is, are we specifying things that must not be implemented now and in the future, because doing so violates a property we must uphold (if so: which)? Or are we specifying things we're not doing in this effort but could be done tomorrow? (in which case, they shouldn't be disclaimed at all and should not be present in the spec, because a future effort could read this spec and refuse to proceed with a design on the grounds that it is verboten)

Comment thread .workhorse/specs/platform/artifacts.md Outdated

## Group-scoped artefacts
A group-scoped artifact rests as an object in its own group's storage, under a prefix of its own apart from the group's backup repo, and a registration placing one anywhere else is refused.
Canopy reads it on a caller's behalf by assuming the group's storage role confined to reading that prefix (see [BAK](../public-server/backup.md)), and streams the bytes to the caller, so the file rests only in the group's storage and is readable only through Canopy.

@passcod passcod Sep 4, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, see, the problem with this is that now we're putting artifact data into a backup bucket. That's a very different access, retention, and audit pattern we're overloading. It also means that we're billing artifacts as backups, or alternatively not billing backups as backups anymore.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this means these artifacts are no longer "canopy is just an index", they're "canopy stores these artifacts". That might justify being a whole separate spec and mechanism (even if it's exposed in the same way UI/API wise).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By which point the language and API surface can change:

  • not registration, but upload
  • uploader has to provide a digest for integrity, but canopy verifies that on upload, and then generates its own suite of digests (across different algorithms) for downloaders to use
  • etc

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.

2 participants