0007 — Library Architecture and Three-Tier Video Hosting Policy¶
- Status: Accepted
- Date: 2026-05-09 (revised from earlier TutorLMS-era draft)
- Decision owners: Gina Lyn Cox · Operations Lead
- Related: ADR-004 (Forms Permissions) · ADR-005 (BuddyBoss Platform) · ADR-006 (Self-Hosted Moodle LMS) · ADR-008 (Guild ↔ Ganjier Brand Relationship) ·
guildcommerce-core-plugin
Context¶
Beyond formal cert-bearing courses (ADR-006, hosted in Moodle), the Guild needs to publish:
- Non-cert webinar replays — recordings of Guild Hour, town halls, expert sessions, board education that don't issue credentials or track CE hours
- Resource documents — downloadable templates, guides, reference PDFs, datasets, tools, links
- Reference articles — explainer content that isn't structured as a course
These three categories don't belong in Moodle. Moodle is for cert-bearing learning with completion tracking, gradebook, and certificate issuance. Non-cert content needs only browseability, search, permission gating, and (for video) a way to play.
But members shouldn't have to learn two systems to find learning content. They should see one Learning experience that surfaces Moodle courses, replays, and resources together — one search bar, one permission model, one nav.
Video content also varies in sensitivity. Public marketing videos shouldn't sit at the same trust tier as a recorded board executive session. The Guild needs a tiered video-hosting policy that matches each piece of content to a host with appropriate access controls.
Decision¶
Where content lives¶
| Content type | Where | Why |
|---|---|---|
| Cert-bearing courses (issue certificates, track CE hours) | Moodle (ADR-006) | Built for graded sequential learning + cert issuance |
| CE-eligible webinar replays | Moodle (as a "Webinar Library" course with completion tracking) | Members earn CE hours; Moodle does this natively |
| Non-cert replays (Guild Hour, town halls, casual content) | WordPress (custom post type replay) |
No CE tracking needed; just browseable + permission-gated |
| Resource documents (PDFs, templates, datasets) | WordPress (custom post type resource) |
File library with search, tags, and permission gates |
| Reference articles | WordPress (native pages or resource type with format: article) |
Same WordPress content engine |
| Member-submitted content (case studies, photos) | BuddyBoss activity / groups | Native fit |
Three-tier video hosting policy¶
| Audience tier | Video host | Why |
|---|---|---|
| Public (Honey) | YouTube unlisted | Free, fast, embeddable, fine for non-sensitive |
| Internal (Mint) | YouTube unlisted, gated by WordPress permission render | URL-leak risk acceptable; obscurity + WP gate is enough |
| Restricted (Lavender) | Google Drive shared folder under Workspace | Real authentication, audit trail, revocable, watermark-capable |
The same replay custom post type handles all three tiers — a host field stores youtube or google_drive, and the page template renders the right embed.
Unified Learning experience¶
A single /library/ archive page renders cards across Moodle courses + WordPress replays + WordPress resources, all filtered by the same Form O permission matrix.
Library architecture¶
Custom post types in guildcommerce-core-plugin¶
guildcommerce-core-plugin/
├── lms-bridge/ (ADR-006: SSO + Moodle API + completion sync)
├── ce-ledger/ (ADR-006: writes CE rows on Moodle completion)
└── library/ (THIS ADR)
├── post-types/
│ ├── replay (recorded video session, non-cert)
│ └── resource (PDF, link, tool, dataset, template, article)
├── taxonomies/
│ ├── topic (cultivation, retail, compliance, ethics, etc.)
│ ├── format (video, pdf, link, article, tool, dataset)
│ └── audience (public, internal, restricted)
├── permissions/ (reuses Form O matrix → BuddyBoss member types)
└── views/
├── archive (unified library page: Moodle courses + replays + resources)
├── single (replay player + metadata; resource detail + download)
└── search (filtered search across all three content types)
Replay record schema¶
title: "Guild Hour — March 2026: Member Q&A with the Board"
host: youtube # youtube | google_drive | self_hosted
youtube_id: dQw4w9WgXcQ # for YouTube unlisted
drive_file_id: null # for Google Drive
audience: internal # public | internal | restricted
recorded_date: 2026-03-15
duration_minutes: 58
presenters: ["Gina Lyn Cox", "Founding Board"]
topics: ["governance", "membership"]
related_forms: [] # e.g. ["S"] for Form S consent verification
related_courses: [] # cross-link to Moodle courses if relevant
consent_verified: true # Form S signed by all on-camera participants
retention_years: 7
Note on cert-eligible replays. A recording that is intended to award CE hours is not a
replaypost type — it is published as a video lesson inside a Moodle course (typically the "Webinar Library" course). Thereplaypost type is only for non-cert recordings. This keeps cert-bearing content unified inside Moodle and avoids two paths to CE awards.
Resource record schema¶
title: "Volunteer Onboarding Checklist"
format: pdf # pdf | link | tool | dataset | article
audience: internal
file_path: /resources/volunteer-onboarding-checklist.pdf
external_url: null
topics: ["volunteers", "onboarding"]
related_forms: ["B"] # related Guild Navigator agreement
retention_years: 7
Unified Learning hub¶
The member portal surfaces one Learning hub that combines all three sources:
┌─────────────────────────────────────────────────┐
│ Your Learning │
├─────────────────────────────────────────────────┤
│ 📚 My Courses (Moodle API: enrolled) │
│ 🎓 My Certificates (Moodle API: completed) │
│ ⏱ CE Hours: 12.5 (ce-ledger module) │
└─────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────┐
│ Browse the Library [search box] │
├─────────────────────────────────────────────────┤
│ Tabs: [All] [Courses] [Replays] [Resources] │
│ Filters: Topic ▼ Format ▼ Audience ▼ Year ▼ │
│ │
│ [thumbnail grid mixing Moodle courses + WP │
│ replays + WP resources, all permission- │
│ filtered, all opened in their native context]│
└─────────────────────────────────────────────────┘
Clicks open in the right context:
- A course card → opens Moodle (SSO bridge keeps the user authenticated, no second login)
- A replay card → opens a WordPress page rendering the YouTube or Drive embed
- A resource card → opens a WordPress page with the download link or external URL
The query merges three sources:
- Moodle REST API for enrolled + browseable course catalog (cached in WP)
- WordPress query for
replaypost type - WordPress query for
resourcepost type
All three respect the same Form O permission matrix.
Three-tier video hosting policy — detail¶
Public (Honey) — YouTube unlisted¶
- Default host for marketing videos, public Guild Hour episodes, public-facing explainers
- Unlisted (not searchable, not on channel page) but URL-shareable
- Embedded as standard YouTube iframe in the WP
replaypage - No login required to watch
Internal (Mint) — YouTube unlisted with WordPress gate¶
- Same hosting mechanism as Public, but the embed is not rendered to non-members
- WordPress page checks
bp_get_member_type()against the replay'saudiencetier - Authorized: iframe renders, member watches
- Unauthorized: standard "your role doesn't include this content" notice; iframe never reaches the HTML
- The unlisted YouTube URL is stored in the WP database, only visible to admins
- This is security through obscurity for the URL itself; the WP gate is the real lock
- Acceptable for member-only content where URL leakage to a non-member is not a serious harm
Restricted (Lavender) — Google Drive¶
- For Form K-tier content (board executive sessions, legal/financial-sensitive recordings, emergency-access training)
- Uploaded to a shared Google Drive folder under the Guild's Workspace tenant
- Folder access controlled by Drive sharing ACLs, mapped to BuddyBoss member types via the Form O matrix
- Embedded via Drive's iframe player; viewer must be signed into a Google account with explicit access
- Workspace Business+ tier provides:
- Audit log of who viewed and when
- Email-watermarked playback (deterrent against re-recording)
- One-click revocation
- Not on YouTube under any circumstances — even unlisted
Drive folder structure¶
Guild Drive (Workspace tenant)
└── Guild Recordings/
├── Guild Recordings — Restricted/
│ (Access: Board + Officers + counsel)
│ └── 2026-Q2-Board-Executive-Session.mp4
│
└── Guild Recordings — Restricted — Legal Privilege/
(Access: Board officers + counsel only)
└── 2026-04-Privileged-IP-Discussion.mp4
Each subfolder's access list maps to a member-type set in Form O. Quarterly access review (per ADR-004) compares Drive folder ACLs against current Form O assignments.
The "do not record" default¶
For genuinely sensitive board executive sessions, the default is to not record at all. Drive is for the rare exception where a recording is genuinely needed (board training session, archived legal briefing). Discussion of the recording happens before the session, with explicit Form S consent from all participants and explicit access-list confirmation.
Why YouTube unlisted is acceptable for Public + Internal¶
- YouTube's unlisted-URL guess space is large enough that random discovery is effectively impossible
- The real risk is intentional sharing by an authorized member to an unauthorized viewer
- For Public content: not a problem (anyone can view anyway)
- For Internal content: low harm — Guild internal videos are professional, brand-safe, and not catastrophic if leaked
- For anything where leakage would be material harm: tier it Restricted, host on Drive
Why Google Drive for Restricted¶
- Already part of the Guild's Workspace stack — zero incremental cost
- Real authentication (Google account + ACL membership), not URL obscurity
- Audit log records every view (Workspace Business+)
- Revocation is one click
- Watermarking discourages re-recording
- Shared folder ACLs are auditable against Form O matrix
- Familiar to admins (no new system to learn)
Why not Bunny.net Stream / Cloudflare Stream / Vimeo / self-hosted¶
| Option | Why not |
|---|---|
| Bunny.net Stream | Costs money for a problem already solved by YouTube + Drive |
| Cloudflare Stream | Same |
| Vimeo Plus | $7/mo, fine for Public but no advantage over YouTube unlisted |
| Self-hosted MP4 on Cloudways | Eats compute resources; no adaptive bitrate; no audit log |
| Wistia free tier | 10-video cap doesn't fit |
Cost¶
| Component | Cost |
|---|---|
| YouTube unlisted hosting | $0 |
| Google Drive (existing Workspace tenant) | $0 incremental |
Library module in guildcommerce-core-plugin |
$0 (we own it) |
| Custom post types, taxonomies, search, views | $0 |
| Total | $0/mo |
Operational implications¶
See programs/learning/README.md for the full publication workflow. Key points:
- Every recording requires Form S (Media Release) signed by every on-camera participant before publication
- Audience tier is determined per Form O matrix
- Restricted? → Drive folder upload + ACL verification
- Public/Internal? → YouTube unlisted upload + captions
- WP
replayrecord created with correcthost,audience,consent_verified: true - Test playback as a non-authorized member confirms gate works
- Quarterly access review (per ADR-004) reconciles Drive ACLs vs Form O
Consequences¶
Positive:
- $0 ongoing cost
- Members see one Learning experience even though three systems back it
- Cert content stays in Moodle where the gradebook + certificate engine lives
- Non-cert content stays in WordPress where the brand + community + permission model lives
- Real auth on Restricted content via Drive
- Permission model is consistent with forms (Form O is canonical)
- Workspace audit log gives the Guild a defensible chain-of-access record for sensitive recordings
Negative / risks:
- Three content sources to keep visually + functionally coherent in the unified library view
- YouTube ToS could change; unlisted policy could shift (low likelihood, mitigated by Drive being available as backup)
- Google Workspace tier dependency (we need Business Standard+ for audit log + watermarking; verify current tier)
- Members on locked-down corporate networks may have YouTube blocked — Restricted content on Drive doesn't suffer this, but Public/Internal content might
- Member-shared YouTube unlisted URLs to non-members is a real risk for Internal-tier content; explicitly accept this and tier accordingly
When to revisit¶
- YouTube unlisted policy materially changes
- Workspace tier downgrade or migration (would require finding a new Restricted host)
- Member harm event traceable to a leaked unlisted URL (forces tier reclassification)
- Cert-eligible-replay volume is high enough that managing them inside Moodle's "Webinar Library" course feels heavy — could split into multiple Moodle courses or a dedicated Moodle category
- Library traffic exceeds reasonable Cloudways performance limits (Library is mostly metadata, not video, so unlikely)
Implementation¶
| Step | Owner | Status |
|---|---|---|
Build library module in guildcommerce-core-plugin |
Full-stack dev | Pending |
Register replay and resource custom post types |
Full-stack dev | Pending |
| Register topic / format / audience taxonomies | Full-stack dev | Pending |
| Build unified library archive page that merges Moodle catalog + replays + resources | Full-stack dev | Pending |
| Verify Workspace tier supports audit log + watermarking | Sysadmin | Pending |
Create Guild Recordings Drive folder structure with ACLs |
Sysadmin | Pending |
| Map Drive ACLs to Form O matrix | Operations Lead | Pending |
| Update Form O to include Library content as a permission row | Operations Lead | Pending |
| Set up "Webinar Library" course in Moodle for CE-eligible replays | Education chair + sysadmin | Pending |
Document publication workflow in programs/learning/README.md |
Operations Lead | This commit |