Add Docker-style image tagging and decouple content / repositories - #425
Add Docker-style image tagging and decouple content / repositories#425chruffins wants to merge 20 commits into
Conversation
8fe5d5f to
6c6cb0f
Compare
-->
✱ stlc build✅ go code · compare
✅ python code · compare
✅ typescript code · compare
Diagnostics: ❗ 0 new / 1 total error, 💡 0 new / 5 total note
Build metadata
This comment is auto-generated by stlc and is kept up to date as you push. |
|
companion PR here: kernel/hypeman-cli#65 |
5fc6e04 to
fe0fa4e
Compare
|
mentioned to assess this directory layout: and if the migration is worth it or if we should stick to existing for now. un-requesting review until pinged again. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6149b26. Configure here.
| if len(refs) > 0 || contentPullInProgress(p, digestHex) || (preserveDigestOnly && contentIsDigestOnly(p, digestHex)) { | ||
| return nil | ||
| } | ||
| } |
There was a problem hiding this comment.
Legacy tree retained after digest delete
Medium Severity
removeDigestIfUnreferenced now returns early whenever shared content is still referenced, an in-flight pull exists, or digest-only content should be kept. That early return also skips removing the repository-local legacy digest directory. Previously the legacy tree was always removed first, and only content removal was gated. Deleting a digest that still has aliases in another repository therefore leaves an orphaned legacy tree on disk, which breaks the dual-layout cleanup path covered by TestDeleteDigestRemovesLegacyTreeWhenContentIsReferenced.
Reviewed by Cursor Bugbot for commit 6149b26. Configure here.


summary
Kernel browser sessions and app deployments run as VM-backed instances. This PR adds Docker-style local image tagging and separates immutable bootable image content from mutable repository/tag references.
A ready Hypeman image can be retagged and pushed without pulling or reconverting it. One converted rootfs is stored per content digest, while repository tags remain lightweight references. Existing legacy image trees remain readable during the migration.
1. pre-existing flows + new flows
existing pull and lookup flow
new local tagging flow
Example:
Tagging does not pull or reconvert the image. The companion CLI changes are in
kernel/hypeman-cli#65.2. changes to the data model
There is no database schema or migration.
The API adds:
The endpoint returns explicit errors for invalid references, missing sources, and non-ready sources.
The logical ownership model is now:
The existing image metadata format remains compatible. Tags are represented by filesystem references rather than a new database table.
This matches the app platform’s existing deployment identity: deployments retain both an image reference and an image digest. The reference is a mutable lookup name; the digest identifies the immutable image used by the VM.
3. changes to filesystem layout
legacy layout
On macOS, the rootfs uses
rootfs.ext4.content-addressed layout
The content directory owns the converted rootfs. Repository/tag paths are references and do not contain another copy of the image.
Readers support both layouts:
4. why change the filesystem layout
protect the bootable browser artifact
Hypeman converts OCI layers into an EROFS or EXT4 disk that boots the browser VM. That converted disk is the expensive runtime artifact; names such as
chrome:stableand deployment-specific tags are only references to it.Multiple names should not create multiple bootable disks or change the bytes used to start a browser session.
keep app deployment identity immutable
The app platform stores an image digest for deployments and app versions. A deployment must be able to start, roll back, or be recreated from the same digest even after a mutable tag moves forward.
Content-addressed storage makes the digest the local content owner and keeps aliases from creating separate image copies.
support host-local caching
Browser sessions and app invocations may run on different hosts over their lifetimes. A host can receive or prewarm a digest, materialize whatever repository/tag reference it needs, and start the VM from the same cached rootfs.
The host does not need to preserve every repository name that previously referenced the image.
make cleanup and accounting correct
Deleting one tag must not delete content still needed by another tag, app version, browser session, or digest-only reference. Separating content from references lets cleanup retain a digest until its final reference disappears.
Hard-linked aliases can also be counted once by physical inode, so repository aliases do not inflate disk usage.
preserve compatibility and enable promotion
Existing legacy images are readable without an offline migration. Cross-repository tagging promotes legacy content by hard-linking the rootfs into the shared directory, writing shared metadata, atomically installing references, and removing the duplicate legacy tree.
The shared content boundary also provides a clear future home for digest-level prewarming, eviction, verification, replication, backup, and restore.
validation
mkfs.erofs, registry access, and host virtualization supportNote
High Risk
Reworks image storage, lookup, deletion, and disk accounting for bootable rootfs artifacts. Layout selection and promotion bugs could delete or mix content, or mis-account host disk.
Overview
Adds Docker-style local image tagging so a ready image can be retagged (including across repositories) without pulling or reconverting it, via
POST /images/{name}/tag(ImageWrite) andhypeman tag.Splits on-disk layout into shared content (
images/content/<digest>) and repository tags (images/repositories/...). Cross-repo tags promote legacy trees by hard-linking the rootfs, atomically installing tag symlinks, then dropping the duplicate digest dir. Readers still accept the old per-repo layout until promotion.Deletes now drop tags in the requested repository only and keep shared content while other tags, digest-only refs, or in-flight pulls exist. Disk accounting counts hard-linked aliases once. Builds install the rootfs atomically;
GetImage/DeleteImageuse the requested reference name.Reviewed by Cursor Bugbot for commit 6149b26. Bugbot is set up for automated code reviews on this repo. Configure here.