⬆️(collaboration) upgrade yhub to 0.9.0 and delete superseded blobs

The S3 persistence plugin records the version id of the object it wrote
and names that version when it deletes it. On a versioned bucket - what
a deployment runs - a delete that names no version deletes nothing: it
writes a delete marker and keeps every version underneath. Each
compaction supersedes the blobs of the one before, so what was kept was
every version of every document ever written, a document someone asked
to erase included, still readable by anyone who can list versions. On
AWS this needs s3:DeleteObjectVersion, which a policy granting
s3:DeleteObject alone does not cover.

Blobs are written to the bucket for every branch of a document.

YHUB_S3_PERSISTENCE now governs only whether new blobs are written
there. The plugin itself is attached whenever the YHUB_S3_* settings
name a bucket, on or off, because reading is the half that must never
be taken away: a row pointing at an object is unreadable without the
plugin that wrote it, and yhub reports such a version as having no
content rather than as an error. Turning the toggle off stops the
writing and leaves the reading alone; it is the settings, not the
toggle, that a deployment whose bucket holds anything must keep. Half a
configuration is a startup error naming what is missing, as before.

The dev stack keeps the toggle off and creates its bucket versioned, so
flipping it on exercises what a deployment runs rather than a simpler
case. Its createbuckets job needed fixing to do so: the folded yaml
block joins its lines with a space, so the trailing backslashes reached
the shell as an escaped space glued to the next word and everything
past the first && silently did nothing - the media bucket never had
versioning enabled either.

Signed-off-by: Kevin Jahns <kevin.jahns@protonmail.com>
This commit is contained in:
Kevin Jahns
2026-09-21 14:47:57 +02:00
committed by Manuel Raynaud
parent 697d88065a
commit bd4c8a5c6c
11 changed files with 162 additions and 67 deletions
+1 -1
View File
@@ -386,7 +386,7 @@
| `yhub.envVars.LEGACY_S3_REGION_NAME` | Region of the legacy bucket, when its provider needs one | |
| `yhub.envVars.LEGACY_S3_BUCKET_NAME` | Name of the legacy Django media bucket (default: impress-media-storage) | |
| `yhub.envVars.LEGACY_S3_SIGNATURE_VERSION` | How the calls to the legacy bucket are signed, s3v4 or v4 (default: s3v4) | |
| `yhub.envVars.YHUB_S3_PERSISTENCE` | Set to "true" to store the document blobs in a bucket instead of the yhub database — read src/yhub-server/README.md first, it cannot be turned back off | |
| `yhub.envVars.YHUB_S3_PERSISTENCE` | Set to "true" to write new document blobs to a bucket instead of the yhub database — the YHUB_S3_* settings attach the bucket whether or not this is on, read src/yhub-server/README.md first | |
| `yhub.envVars.YHUB_S3_ENDPOINT_URL` | Required by YHUB_S3_PERSISTENCE, endpoint of the bucket the blobs are stored in, without a path (e.g. https://s3.example.com) | |
| `yhub.envVars.YHUB_S3_ACCESS_KEY_ID` | Required by YHUB_S3_PERSISTENCE, read/write/delete access to that bucket (or YHUB_S3_ACCESS_KEY_ID_FILE) | |
| `yhub.envVars.YHUB_S3_SECRET_ACCESS_KEY` | Required by YHUB_S3_PERSISTENCE, secret of the key above (or YHUB_S3_SECRET_ACCESS_KEY_FILE) | |
+6 -5
View File
@@ -942,10 +942,11 @@ jwtKeys:
## - `LEGACY_S3_*`, turned on by `SOFT_MIGRATION`, is the legacy Django media
## bucket it reads old documents *out of*. Not the backend's `AWS_S3_*`,
## which names the same bucket for the backend's own use,
## - `YHUB_S3_*`, turned on by `YHUB_S3_PERSISTENCE`, is a bucket of its own it
## stores the document blobs *into*, instead of its PostgreSQL database.
## Read `src/yhub-server/README.md` before enabling it: a document persisted
## this way cannot be read back once the setting is removed.
## - `YHUB_S3_*` is a bucket of its own it stores the document blobs *into*,
## instead of its PostgreSQL database, when `YHUB_S3_PERSISTENCE` asks for
## it. Read `src/yhub-server/README.md` before enabling it: those settings
## attach the bucket whether or not the toggle is on, and dropping them from
## a deployment whose bucket holds anything makes those documents unreadable.
yhub:
## @param yhub.enabled Enable the yhub collaboration server, its service and its init-db job
enabled: true
@@ -1060,7 +1061,7 @@ yhub:
## @extra yhub.envVars.LEGACY_S3_REGION_NAME Region of the legacy bucket, when its provider needs one
## @extra yhub.envVars.LEGACY_S3_BUCKET_NAME Name of the legacy Django media bucket (default: impress-media-storage)
## @extra yhub.envVars.LEGACY_S3_SIGNATURE_VERSION How the calls to the legacy bucket are signed, s3v4 or v4 (default: s3v4)
## @extra yhub.envVars.YHUB_S3_PERSISTENCE Set to "true" to store the document blobs in a bucket instead of the yhub database — read src/yhub-server/README.md first, it cannot be turned back off
## @extra yhub.envVars.YHUB_S3_PERSISTENCE Set to "true" to write new document blobs to a bucket instead of the yhub database — the YHUB_S3_* settings attach the bucket whether or not this is on, read src/yhub-server/README.md first
## @extra yhub.envVars.YHUB_S3_ENDPOINT_URL Required by YHUB_S3_PERSISTENCE, endpoint of the bucket the blobs are stored in, without a path (e.g. https://s3.example.com)
## @extra yhub.envVars.YHUB_S3_ACCESS_KEY_ID Required by YHUB_S3_PERSISTENCE, read/write/delete access to that bucket (or YHUB_S3_ACCESS_KEY_ID_FILE)
## @extra yhub.envVars.YHUB_S3_SECRET_ACCESS_KEY Required by YHUB_S3_PERSISTENCE, secret of the key above (or YHUB_S3_SECRET_ACCESS_KEY_FILE)