Session Log: AV7's invisible-content gap found and fixed, AV6 shipped, AV10 scoped
Date: 2026-09-14 (afternoon, continuing the same day's AV8 session) Driver: Yuji Shinozaki (with Claude Code) Outcome: Found and fixed a real gap that made every grouped AV video/audio node invisible in Drupal to everyone, including a site administrator. Shipped AV6 (KMaps display wiring). Scoped AV10 (Kaltura configuration layer) from a direct inspection of the existing contrib module, not from the sprint doc's design note alone. Three new deferred notes filed for genuinely open findings.
PRs merged: #201 (AV7 permission fix), #202 (docs), #203 (AV6), #204 (AV10 scope note).
1. "We can see the content, but only 63 of 7,395 video nodes"
Checking /admin/content?type=video&status=All as the site's administrator
account showed only 63 nodes, not the 7,395 published video nodes AV4
migrated. Chased this precisely rather than guessing:
- Ruled out an
INNER JOINtousers_field_datadropping rows for unmigrated authors — all 7,396 video nodes'uids resolve to real users (the shared D7 user base migrated cleanly; this wasn't an authorship gap). - Ruled out langcode filtering, Views caching, and the classic node_access grant table (which had exactly one row — Drupal's own "no access-restricting module" sentinel, which should grant universal access, not restrict it).
- Found the real mechanism by direct, escalating checks: a
group_relationship->access('view')check on a real grouped video node returned FORBIDDEN — even for the administrator account, which tested positive forbypass node access,bypass group access, andadminister group(Group module's own true super-permission). None of the three overrode it. - Root cause: Group module generates a permission string
(
view group_node:video entity) the moment a content plugin is installed on a group type, but grants it to nobody.shanti_imagehad this wired since Sprint 1;audio/videonever got the equivalent grants when AV4 installed those plugins oncollection/subcollection. Group's own per-plugin access check doesn't defer to the generic bypass permissions the way core's node access system does — a real, documented-now design trap (see [[project-kmassets-sync-writer-bugs]] sibling memoryproject-mandala-statefor the full technical trace).
Fixed (PR #201): mirrored shanti_image's exact permission shape onto
audio/video across all 10 collection/subcollection role configs.
2. Why a one-time fix wasn't enough
Discussed with Yuji whether this is a design risk (it is — Group's per-plugin permission model is fail-closed by design, which is right for security but means every future bundle added to a Group-enabled content type repeats this exact gap unless something catches it) and whether a shared base implementation could provide "universal permissions by default" without losing Group's per-content-type granularity.
Landed on: the permission string is already auto-generated by a shared
base (no code needed per plugin); only the grant needs automating. Built
drush mandala:group-permission-audit [--fix] in mandala_group_inheritance
— derives the canonical permission shape per (group type, role) from
whatever plugins already have grants, with no bundle name hardcoded, so it
stays correct as Sources/Texts add their own bundles later. Verified: it
correctly re-derives the exact real gap from the pre-fix state, and reports
clean post-fix.
3. A deploy near-miss, caught and corrected
Merging PR #201 and then manually triggering a CodePipeline execution
created a real duplicate — the merge's GitHub webhook had already
auto-started a deploy for the identical commit. Caught mid-flight; stopped
the redundant execution with a graceful stop-pipeline-execution (no
--abandon) specifically so the currently-running Terraform/Ansible deploy
action would finish naturally rather than being killed mid-apply — confirmed
by polling the underlying CodeBuild job directly, since CodePipeline's own
stage status stayed showing "Stopping" well after the real job had actually
succeeded. Filed as
[[codepipeline-webhook-plus-manual-trigger-duplicates-deploy]] so the next
person (or session) doesn't re-trigger this.
Verified post-deploy: mandala:group-permission-audit reports 0 drift, the
admin content listing shows all 7,395 video nodes, and the specific
group_relationship->access('view') check that was FORBIDDEN is now
ALLOWED.
4. AV6: KMaps field display wiring (done)
Scoped and built in one pass. All 6 KMaps fields already had data fully
migrated by AV4; the only gap was that no core.entity_form_display/
core.entity_view_display config existed at all for audio/video, so
viewing fell back to the field type's plain default formatter instead of
the rich popover UX Images has.
Built both displays by taking Drupal's own computed default (via
entity_display.repository, so every non-KMaps field keeps exactly the
behavior it already had) and overriding only the 6 KMaps fields. Every other
custom AV field (field_video, field_workflow, the PBCore set,
field_transcript) lands in hidden — not a regression, the honest
reflection that those fields never had a display default to begin with
(created via migration, not Field UI) and their real presentation is AV9's
job.
Hit, and worked around, a real config:export hazard along the way: a
bare drush config:export after building the two new displays touched 24
files, not 2 — it re-serializes the entire active config, and in the
process silently deleted the AV8 rationale comment block from
mandala_kmassets_sync.settings.yml (added the same morning). Reverted the
20 unintended files, kept only the 4 real ones. This is the third
documented recurrence of config:export's comment-stripping behavior and
had never been formalized — filed as
[[config-export-not-scoped-strips-comments]].
Verified against real migrated content, both locally (DDEV, which turned out to already have the full AV dataset) and again on dev-0 post-deploy: rendered a real video node through the new display and confirmed real KMaps taxonomy data renders correctly via the popover formatter.
5. AV10: Kaltura configuration layer, scoped
Rather than re-deriving the design from the sprint doc's existing notes
alone, inspected the actual drupal/kaltura_media contrib module directly:
it already provides a working-but-minimal baseline (a kaltura field type
+ a kWidget.embed()-based formatter with no dimension/delivery/
rotate-stretch support), and confirmed AV4 already migrated real per-node
values — frozen from a single hardcoded migration-time constant, which is
exactly what AV10 needs to stop being the source of truth for.
Wrote up a full scope note
(docs/planning/av10-kaltura-configuration-layer.md)
proposing a kaltura_player_config config entity (modeled on image_style)
plus a site-level settings object, and traced the exact secret-delivery
pattern already proven for SimpleSAML/solr-proxy in
terraform-infrastructure so AV11's eventual credential wiring is a
two-line addition to an established mechanism, not a new design.
What's left
- AV9 (Kaltura player formatter + gallery UI) — now has a real design to build against once AV10 exists, at least minimally.
- AV10 itself — scoped, not built.
- AV11/AV12/AV13 — unchanged, depend on AV10.
- AV7's two AV-specific realms (
group_access_uva_member,mb_collection_admin) — independent of everything above, can run in parallel whenever there's capacity. - Three new deferred notes filed this session, none blocking: [[config-export-not-scoped-strips-comments]], [[codepipeline-webhook-plus-manual-trigger-duplicates-deploy]], [[images-title-sort-s-possible-silent-truncation]] (carried over from the morning's AV8 work, formalized now).