Files
summercms/.planning/notes/apparatus-dissolved-into-framework.md

3.8 KiB

title, date, context
title date context
Decision: Apparatus is dissolved into the framework, not ported as a plugin 2026-09-28 /gsd-explore during Phase 11 discuss (job manager gray area)

Decision: Apparatus Is Dissolved Into the Framework

Date: 2026-09-28 Status: Accepted for Phase 11 onward

Decision

Golem15\Apparatus is not ported as a plugin. The few pieces the ported plugins depend on move into summercms.go as framework packages; the rest is dropped or deferred. No apparatus plugin exists in fonoteka.go.

Job record: summer_jobs

The PHP JobManager (golem15_apparatus_jobs, JobStatus, ApparatusQueueJob) becomes a framework job package over River.

  • Table name is summer_jobs (framework-owned, no Golem15 plugin prefix).
  • Columns and semantics are kept from PHP: integer auto-increment id, label, status, progress, progress_max, user_id, is_admin, is_canceled, metadata, timestamps.
  • JobStatus integers are kept: IN_QUEUE=0, IN_PROGRESS=1, COMPLETE=2, ERROR=3, STOPPED=4.
  • Integer ids stay the public contract: the CSV import API exposes them as import_job_id / match_job_id.
  • At cutover, rows from golem15_apparatus_jobs are copied into summer_jobs with ids preserved (same approach as Phase 9's backend_users).
  • River executes the work; the summer_jobs row is the record that API responses, progress and cooperative cancellation (is_canceled) read.
  • A queue:clear command (River bulk delete) belongs with this package. A Jobs admin screen can later be plain admin YAML.

Triage of the rest of Apparatus

Apparatus piece Consumers in ported plugins Disposition
JobManager, JobStatus, ApparatusQueueJob, jobs table fonoteka CSV import/match, wishlist digest Framework job package over River, summer_jobs (above)
RequestSender (curl wrapper, bearer, multipart, private-IP guard) feedback G15OfficeClient, golem AIService Do not port the class. Extend fetchguard into a guarded http.Client (POST/PUT/multipart/bearer). fetchguard checks the IP at dial time, which closes RequestSender's resolve-then-connect DNS-rebind gap
RedactCredentialsTap (log scrubbing) logging config Framework slog handler with the same sensitive keys and patterns
SafeExceptionResponse (generic 500 message outside debug) user ApiController, golem AIService Verify surf already covers it; otherwise a small framework helper
DependencyInjector, BackendInjector, NeedsDependencies, Resolver facade, DatabaseManager, Pipeline/Pipe internal Drop: the backpack service registry, constructor injection and Go middleware chains replace them
RouteResolver, Messaging/ConfirmModal/InfiniteScroll components, HumanDateExtension, TranslApiController, theme scanner hook, BlogUrlValidationMiddleware CMS pages / Twig Drop: v1 is headless
KnobWidget, Sensitive, ListToggle form widgets; BackgroundImportExport behavior Winter backend Drop for now; Sensitive may return as an admin SPA field type (Phase 10.1)
PersonalApiToken for backend admins, TokenAuthenticate, ForceJsonResponse none in Płytarium Defer (todo: backend admin API tokens)
Mail import/export/reset, SaneGitModules, Optimize, FakeJob, BrowserGeneration, generic CsvImportJob, HtmlSanitizer none (fonoteka documents it does not use the generic CsvImportJob; HtmlSanitizer is used only inside Apparatus) Drop

Consequences

  • Phase 11's job manager service (JOBS-01) is the framework summer_jobs package; its migration ships with the framework.
  • Phase 14 plugins (feedback, AI recognition, Discogs) use the extended fetchguard client instead of a RequestSender port.
  • The Phase 15 cutover runbook must include the golem15_apparatus_jobs → summer_jobs copy.