Skip to content

P9a-5a: platform owns the legal sections, with hal's last ruled sentence and the general part's 30-day sentence #289

Closed

Description

@FlexOr2

Parent: #173

P9a-5a: platform owns the legal sections, with hal's last ruled sentence and the general part's 30-day sentence

Caller: #173, slice row P9a-5 ("The tunnel line and hal's apex move, his sentence stands, hal's exit is named, the live body equals built/, …"). P9a-5b (the live go) needs this slice first: the page that goes live must hold every sentence hal serves and the ruled 30-day sentence, and one owner must hold the sections from the go on. P9a-6 (the „KI-Dienst“ rename) comes after both.

Ruled

  • The operator, 08.11.2026 („alles nach empfhelung“, P9: legal pages, person export and erasure, AI keys and expiry checks move from hal #173's body): "P9a: the legal pages move as soon as the platform builds them, before the big cutover." and "P9a: the general text gains the sentence that logs are kept at most 30 days." This newer ruling replaces Platform on k3s and Flux: from an empty PC to every app live, with hal archived #1's card line 1 (A, 06.11.2026: the live pages stay on hal until the cutover) for the legal pages.
  • P9: legal pages, person export and erasure, AI keys and expiry checks move from hal #173 card line 2, ruled „other“ on 09.11.2026: „sollten die apps die fristen schreiben oder wir global und die apps halten sich dran!“ The head's reading (P9: legal pages, person export and erasure, AI keys and expiry checks move from hal #173, comment of 09.11.2026 09:19Z, not the operator's words): the general part names the 30-day period, and the apps refer to it instead of stating their own server-log period, which is option A's sentence and cost. Option A's effect gives the sentence: „Was unsere Dienste auf dem Server ins Protokoll schreiben, löschen wir, bevor es 30 Tage alt ist; war der Server ausgeschaltet, kurz nach seinem nächsten Start.“ Its contract: infrastructure/legal/sections/allgemein/datenschutz.html gains the sentence verbatim, with a new stand.toml date; platform's copy becomes the sections' owner, and the equality check against hal's sections is dropped in the same slice; songmaker's and presentator's heads each get an item to align their log sentence.
  • P9: legal pages, person export and erasure, AI keys and expiry checks move from hal #173 invariant 3: "The legal text is the operator's: sections move word for word, a changed sentence is his." The operator's earlier ruling: hal's legal texts are taken byte for byte, apart from what he changes.
  • hal#1168, card ruled A on 09.11.2026 in chat: #sprachdienst says that a person's token can also carry the user name, the name and the e-mail address, depending on the app, and that the speech service receives them with it. hal landed it as hal#1177 (ed6de88e) after the pin a5c2342 that platform's copy and its check hold.

The head's choice, not ruled: the heading „Server-Protokolle“ with the id server-protokolle, after „Nutzung unter Pseudonym“, so an app's part can link the period instead of stating its own; the ruled text names the sentence and the general part, not a heading.

Why the sentence is true at the go

  • songmaker's head, 09.11.2026: since songmaker#2296 (v2026.11.05.2 and later) every songmaker service logs with driver: journald, tag: "{{.Name}}", with no max-size or max-file; songmaker's own code writes no ACE-Step log file (the worker logs to stderr and reads its child over a pipe).
  • The head's read of the PC's Docker, 09.11.2026, hal untouched: every running songmaker container (web, scoring-worker, music-worker, acestep-worker-0, postgres, redis, prometheus, grafana, alertmanager) and presentator's two containers use the log driver journald.
  • hal's daily journal clean holds every journal line at most 29 days (hal#167's arithmetic, --vacuum-time=28d); the platform's pod logs go after 28 days and Loki's copy after 28 days (AGENTS.md's host step and infrastructure/loki/).

What it builds

  1. hal's last ruled sentence. infrastructure/legal/sections/speech-runtime/datenschutz.html becomes hal's file at ed6de88e byte for byte (one sentence added in „Wer zugelassen ist“), its stand.toml entry date = 2026-11-09 (the file's %cs there) and its sha256. The first pushed commit moves hal_commit to ed6de88e with the sections diff still in place, so CI proves equality with hal's last legal commit once.
  2. The 30-day sentence. infrastructure/legal/sections/allgemein/datenschutz.html gains, after „Nutzung unter Pseudonym“, <h2 id="server-protokolle">Server-Protokolle</h2> and a <p> holding the ruled sentence verbatim; its stand.toml entry takes the landing day and the new sha256. STABLE_IDS["datenschutz"] in src/legal/src/legal/pages.py gains server-protokolle, with its test in src/legal/tests/test_pages.py. mise run legal:build regenerates built/datenschutz.html; its Stand reads the landing day.
  3. The owner. The second commit deletes the sections diff -r from tests/legal/legal_sections_assets_and_headers_equal_hals_at_commit.sh. The stylesheet, header and appkit checks stay against ed6de88e until P9a-5b, since hal serves the apex until then. The checks step's name drops "legal sections".
  4. AGENTS.md is not changed (the operator, 09.11.2026, platform carries the fleet document set: AGENTS.md within its budget, an architecture overview and runbooks #134 comment 6738858275: no lane changes AGENTS.md). The head names on platform carries the fleet document set: AGENTS.md within its budget, an architecture overview and runbooks #134 the sentence this change makes false: "sections/<unit>/<page>.html are hal's sections at the pinned commit, word for word: a changed sentence is the operator's." (P0 class R, destination Owners; its ruled half stands in P9: legal pages, person export and erasure, AI keys and expiry checks move from hal #173 invariant 3). The clause of the src/legal/ paragraph describing the hal script was already gone at the tip. platform carries the fleet document set: AGENTS.md within its budget, an architecture overview and runbooks #134's phases delete the sentence.

Size: four production files (the two sections, stand.toml, pages.py), about 8 changed lines; they do not split, since a published section, its Stand and the id apps link are one change on the page. Plus the test script, test_pages.py, ci.yml's step name and the generated page.

Proof

CI. checks: the hal script at ed6de88e passes with the sections diff (first commit), then without it; legal:test at 100 % branch coverage, the stable id's test included; legal:build regenerates built/ with an empty diff (part core). cluster's five-paths cell serves the new built/datenschutz.html with its checksum.

Review. diff of the speech section against hal's file at ed6de88e is empty; diff of the general section against hal's at ed6de88e shows only the new heading and paragraph, the sentence equal to the ruled one character for character. built/datenschutz.html holds an app section for each app hal composes today: hopin, presentator, skat and songmaker.

Nothing goes live here; P9a-5b's live check proves the page.

Trace (main 0bf0c46)

  • infrastructure/legal/stand.toml:1-3 (allgemein/datenschutz.html), :17 (speech-runtime); infrastructure/legal/sections/speech-runtime/datenschutz.html differs from hal's at ed6de88e at byte 2719 (hal#1177); the other four sections and all nine frame files equal hal's at origin/main e9cfd360.
  • tests/legal/legal_sections_assets_and_headers_equal_hals_at_commit.sh:9 (hal_commit), :18-21 (the sections diff).
  • .github/workflows/ci.yml:72-73 (the step).
  • src/legal/src/legal/pages.py:29-45 (STABLE_IDS).
  • AGENTS.md:686-687 (R row of P0 part c, base 683-684), :896-901 (D).
  • hal: git log a5c2342..origin/main -- legal/ names only ed6de88e; pyproject.toml's appkit pin is unchanged.

Risk

Material: a public legal page's text and its owner. Opus review at high and a cross-provider final gate. The first review drives:

# Sentence Cell Driven by
1 hal#1168's ruled sentence stands in platform's speech section byte for byte hal script at ed6de88e, first commit CI
2 An edited section carries its new Stand stand.toml sha check in legal:build CI
3 built/ is the build of the committed sources regeneration step CI
4 The page loses no app section ids of hopin, presentator, skat and songmaker in built/datenschutz.html review
5 The sections diff against hal is gone; the stylesheet, header and appkit checks hold hal script CI
6 The 30-day sentence is the ruled one verbatim, the only delta to hal's general section diff review
7 An app part may link #server-protokolle; a link to another unknown id stays refused test_pages.py CI
8 The sentence this change makes false is named on #134 comment review

Rollback: a revert restores the pin a5c2342 and its diff; nothing is live.

Deliberately untouched

  • A log file the vendored ACE-Step fork may write inside its container (vendor/acestep): unverified by songmaker's head; if it exists, the 30-day sentence is untrue for it. Owner songmaker#1714, songmaker's head to verify.
  • songmaker's stale section („nach Speichermenge rotiert (höchstens 50 MB je Dienst)“, the ACE-Step file „die nicht rotiert wird“, „Eine feste Höchstdauer besteht in beiden Fällen derzeit nicht.“) contradicts the general part from the go until songmaker's release with the corrected text. Owner songmaker#1714 finding 6; its wording is the operator's yes in songmaker's repository, not here. presentator's „Eine Aufbewahrungsdauer ist nicht festgelegt.“ lags the same way; its item is opened at P9a-5b.
  • The Keycloak section's token sentence („… bei jeder App basic, profile, roles, groups …, bei den meisten Apps auch email“) and hal#1177's sentence: true at the go, since hal's Keycloak issues every live token until P10 (P10: hal's public services move onto the platform and hal stops #235). A token for the speech service's audience holds only subject and groups #240's realm makes both untrue for access tokens once the platform's Keycloak goes live; A token for the speech service's audience holds only subject and groups #240 already names hal#1177's sentence for removal then. Both are wording the operator rules at P10: hal's public services move onto the platform and hal stops #235's Keycloak slice.
  • The LiteLLM section's „Wie lange die Zeilen der Protokolle aufbewahrt werden, bestimmt die Einstellung des Docker-Dienstes dieses Servers.“: true for hal's LiteLLM, the only one a live app calls (hopin's gateway on the platform is gateway.invalid); it turns false at LiteLLM's move (P10: hal's public services move onto the platform and hal stops #235).
  • The speech section's „Der Dienst hat keine Verbindung ins Internet“ and „jede erreicht ihn über ein eigenes internes Netz“: card line 1 below.
  • hal's sections after this slice: hal's exit item freezes them; hal#1154 (a change of #anmeldung) moves to platform's board.
  • The „Agent-Dienst“ rename: P9a-6.

Done when

platform's speech section equals hal's at ed6de88e with its Stand, the general part holds Server-Protokolle with the ruled 30-day sentence verbatim and its new Stand, server-protokolle is a stable id, the sections diff against hal is gone (platform's copy is the owner), and the two AGENTS.md sentences this change makes false are named on #134.

version = 1
now = "Cut from #173 on 09.11.2026 (P9a-5 split into 5a, the owner and the sentence, and 5b, the live go). hal#1177 (ed6de88e, ruled A on hal#1168) changed hal's speech section after platform's pin. songmaker's head and the PC's Docker confirm journald for every songmaker and presentator container, so the 30-day sentence holds."
next = "Claim with aco start and build. Card line 1 (the speech service) is independent of this build."
done_when = "platform's speech section equals hal's at ed6de88e with its Stand, the general part holds Server-Protokolle with the ruled 30-day sentence verbatim and its new Stand, server-protokolle is a stable id, the sections diff against hal is gone, and the two AGENTS.md sentences this change makes false are named on #134."

scope = [".github/workflows/ci.yml", "infrastructure/legal/built/datenschutz.html", "infrastructure/legal/sections/allgemein/datenschutz.html", "infrastructure/legal/sections/speech-runtime/datenschutz.html", "infrastructure/legal/stand.toml", "src/legal/src/legal/pages.py", "src/legal/tests/test_pages.py", "tests/legal/legal_sections_assets_and_headers_equal_hals_at_commit.sh"]

size = "S"

whole = "One owner change: hal's last ruled sentence, the general part's 30-day sentence with its Stand and stable id, and the end of the sections comparison are one published state of the sections."

[[expectation]]
text = "Der Sprachdienst der neuen Plattform bekommt keine Anfrage einer App, solange er eine Verbindung ins Internet hat."
asked_on = 2026-11-09
ruling = "A"
ruled_on = 2026-11-09
card_hash = "sha256:e11c7874088a0f617f568c7c29b0d745de1bf7b8f4baf7ee4aad3a9605300caf"
via = "board"
question = "Darf deine Datenschutzseite weiter sagen, dass der Sprachdienst keine Verbindung ins Internet hat?"
problem = "Der Sprachdienst auf der neuen Plattform holt einen Schlüssel aus dem Internet; der Satz stimmt nur für den alten."
decision_kind = "product"
area = "Datenschutz"
topic = "Sprachdienst"
recommended = "A"
reason = "Heute erreicht keine Anfrage eines Nutzers den Sprachdienst der neuen Plattform: HopIn hat dort keine Stimme eingestellt, und Presentator nutzt den Sprachdienst des alten Servers, der keinen Weg ins Internet hat und den Schlüssel intern holt. Der Satz stimmt also für jede heutige Anfrage. Nach dem Umzug der Anmeldung kann auch der neue Sprachdienst den Schlüssel intern holen und ganz vom Internet getrennt werden; dann stimmt der Satz dort ohne neue Worte."

[[expectation.option]]
name = "Erst trennen, dann nutzen"
effect = "Keine App schickt Anfragen an den neuen Sprachdienst, bevor er vom Internet getrennt ist; das geht nach dem Umzug der Anmeldung."
notice = "An der Seite ändert sich nichts. Die Stimme von HopIn auf der neuen Plattform kommt erst nach dem Umzug der Anmeldung."
cost = "HopIns Stimme und Presentators Umzug warten auf den Umzug der Anmeldung. Danach ein kleiner Schritt: interne Schlüsseladresse und eine Netzregel."
undo = "reversible"
undo_how = "Die Sperre aufheben und den Satz ändern."
contract = "A new platform item, called by #235's Keycloak go-live and by the first item that points a live caller at apps/speech-runtime (hopin's HOPIN_SPEECH__ORIGIN or presentator's move): jwks_url to Keycloak's in-cluster Service, an egress NetworkPolicy for speech-runtime to cluster DNS and Keycloak only, Keycloak's ingress policy admitting namespace speech-runtime, and a k3d cell that a Pod with speech-runtime's labels reaches Keycloak and neither the Service kubernetes nor github.com. Until it lands, no live caller is pointed at apps/speech-runtime."

[[expectation.option]]
name = "Satz jetzt ändern"
effect = "Der Satz wird so geändert, dass er sagt, dass der neue Sprachdienst den öffentlichen Schlüssel der Anmeldung aus dem Internet holt; Apps dürfen ihn sofort nutzen."
notice = "Im Abschnitt Sprachdienst steht ein geänderter Satz mit neuem Stand."
cost = "Du formulierst und bestätigst einen neuen Satz, der nach dem Umzug der Anmeldung wieder geändert wird."
undo = "reversible"
undo_how = "Den alten Satz in einem neuen Stand zurückholen."
contract = "The operator words the change; platform's speech section carries it with a new stand.toml date before a live caller uses apps/speech-runtime; the egress item of A follows at #235 without a caller gate."

[[expectation.option]]
name = "Wie heute"
effect = "Nichts wird festgelegt; der Satz bleibt, und eine App darf den neuen Sprachdienst jederzeit nutzen."
same_as_today = true
notice = "Der Satz wird falsch, sobald eine App den neuen Sprachdienst nutzt, ohne dass du davon erfährst."
cost = "Nichts zu bauen; das Risiko eines falschen Satzes bleibt."
undo = "reversible"
undo_how = "Später eine der anderen Wahlen treffen."
contract = "No gate; the egress item is opened at #235 without a caller gate."

Activity

  1. added theissue type on Nov 9, 2026
  2. FlexOr2 commented on Nov 9, 2026

    @FlexOr2
    MemberAuthor

    Landed in #324, merge 3223fb0: platform owns the legal sections. Freed: #290.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions