v0.41.0
2026-06-08
- Glean moved to its new home: https://glean.gatheredin.app — the new Gathered suite domain. The old glean-blue.vercel.app URL keeps working and 301-redirects here (root and every path), so existing links and home-screen shortcuts are not broken.
- The App Switcher now links to the *.gatheredin.app addresses for all five Gathered apps. Sign-in, signup, and password-reset links build on window.location.origin, so they adapt to whichever domain is in use. Note: push notifications are tied to the site origin — on your next visit via the new domain, the app re-registers for notifications there.
v0.40.0
2026-05-31
- Signup now tags new auth users with `data: { app: 'glean' }`. Companion change to the shared handle_new_user trigger (rewritten 2026-05-30): the trigger only writes to per-app user tables that match the tag, and Glean's own onboarding still happens via Gathered admin granting app access (which already populates `glean_leaders`). Effect of this change: a Glean signup no longer leaves a stale pending row in Magnify's `profiles` or Squarecana's `sq_users`.
v0.39.0
2026-05-25
- **Privacy fix: stake leadership no longer listed as automatic viewers of a plan.** Scott was seeing 5 stake-level leaders on the 'WHO CAN SEE THIS PLAN' card with the label 'Stake leadership (automatic)' — but at the database level those leaders never had access to the plan body (the narratives / goals / actions / comments tables use glean_can_see_plan_body, which correctly excludes stake-wide). The UI was reporting access that didn't exist. Per the W&SR access model (Handbook 22.4.5), only the member, the bishop of the member's ward, and the leader who created the plan see it by default — stake leadership must be explicitly added by the bishop or the plan author. Removed the stake_leader code path from getPlanAccessSummary entirely; updated the helper copy at the bottom of the access panel to match.
- **Data fix: glean_leaders no longer holds rows for users who don't have Glean app access.** The reconcile_glean_leader trigger that syncs Gather roles into glean_leaders was firing on every gather_user_roles change regardless of whether the user had the G toggle in Gather. Three stake-level users (Blake Bartolomei, Celso Alvarez, vielman23) ended up as Glean leaders despite never having installed Glean. Trigger now gates on user_apps.app_name='glean'; a new user_apps trigger fires reconcile on grant/revoke so the leader row appears/disappears immediately when the G toggle changes. Backfilled the existing table — only Jeff Tingey, Scott Shurtliff, and Brayden Monson remain.
- reconcile_glean_leader extended to recognize ward_org_presidency Gather roles. Maps to 'eq' by default (admins flip eq→rs manually for Relief Society presidents). Preserves an existing eq/rs row's role across reconciliations so a manual grant like Brayden Monson's doesn't get clobbered when Gather fires a sync.
v0.38.1
2026-05-25
- TabBar active icon now swaps to a filled glyph (spec §4 cue). Inactive tabs render the outline SVG, active tab renders the filled variant — applies across Dashboard / Members / Resources / Ask Glean / Settings. Stroke→fill swap mirrors the Ionicons outline→solid pattern used in Knit/Tidings.
- Settings 'Suggest an enhancement' row is now mobile-only (md:hidden). On desktop the corner SuggestionFAB already opens the same modal, so the Help & feedback row was a redundant second entry point. The User guide + Release notes rows stay on both viewports.
- .scroll-pb-fab utility (defined in v0.35 but never applied) now lives on the AppShell main content wrapper, plus a global html scroll-padding rule at mobile widths. Anchor scrolls — like the Home hero bell → #notifications jump — no longer land with the target row sitting under the ChatFab.
v0.38.0
2026-05-25
- Mobile Home hero now carries the spec's search + notification icons in the top-right (§2 of the Glean Mobile + Web Handoff). Search routes to /members where the planlist is now filterable; the bell carries a gold dot and scrolls to the Notifications section on the same page. Replaces the previous heroless greeting on phones.
- Members / Plans list got a client-side search box at the top — sticky on mobile, 16px input font (no iOS zoom on focus), filters by member name / ward / plan owner. Lit up the dormant members.searchPlaceholder + plans.searchPlaceholder locale keys.
- Plan owner auto-assignment is now enforced at the database, not just the app. New BEFORE INSERT trigger glean_plans_default_leader sets glean_plans.leader_id from the inserting user's glean_leaders row (preferring a ward-match) when leader_id is NULL. Prevents the bug from May where Liesl Shurtliff's plan was created with leader_id=NULL — the app was passing leader_id correctly, but this guarantees the data layer always backs it up.
- Data cleanup: removed a duplicate Liesl Shurtliff member record (5767b297-… / Hyde Park 1st / no email) plus its empty draft plan. Canonical Liesl record (f02d5380-…) had a typo email (sendliesl@gmailcom) — fixed to sendliesl@gmail.com so notify flows work.
- Notifications section now has an id='notifications' anchor so the Home hero bell icon's scroll link lands at the right place.
v0.37.0
2026-05-25
- Mobile: new ChatFab — a 56px navy quick-access shortcut to Ask Glean that sits 12px above the tab bar on every screen (except /chat itself), respecting env(safe-area-inset-bottom). Gold notification dot in the top-right. Hidden on desktop where the sidebar's Ask Glean entry already does the job. Implements §5 of the Glean Mobile + Web Handoff.
- Sidebar + tab bar rename: 'Home' → 'Dashboard' and 'Plans' → 'Members' per §4 of the handoff. The /members URL is unchanged; just clearer labels (Glean's data model doesn't distinguish members from plans the way the handoff's prototype envisioned, so two duplicate entries would be misleading).
- Dashboard 4th stat tile: every role-specific dashboard (stake, bishop, EQ/RS) now shows a gold 'Resources' count alongside Total / Pending / Stale. Grid switches to 2-col on mobile, 4-col on md+. Single batched query alongside the existing data fetch — no extra round-trip cost.
- Plan card §3 visual: draft plans now open with a gold-fade Leviticus 19:9–10 verse anchor card; approved plans show a gold progress bar (action steps done / total) above the goals; the 'Submit for Bishop Approval' button is now a full-width gold k-btn (was a navy half-width).
- i18n: nav.dashboard, nav.members, home.statResources added in en + es.
v0.36.0
2026-05-25
- Home page no longer leads with the full About-Glean paragraph on every visit. On mobile the navy wheat-field hero is compressed to ~80px showing 'Good morning, {firstName}' + 'Role · Ward' subtitle. On desktop the navy hero is hidden entirely — the page opens with a plain two-line greeting strip and the dashboard widgets (stat row + plans by ward / needs approval) become the dominant content, matching Section 4 of the Glean Mobile + Web Handoff. The About-Glean blurb still lives on /settings.
- Sidebar active state on desktop switched from the suite-default white-translucent fill to a subtle gold tint (rgba(201,168,76,0.18) bg + text-glean-primary) — same recipe the handoff mockups use, makes Glean's identity visible in nav state without changing chrome color overall.
- Member plan card now gets a status-tinted border ring on /members/[id]: gray for draft, amber for pending, green for approved, orange for expiring, red for expired. Colors match the existing StatusBadge so the chip and the card frame agree at a glance.
- i18n: home.greeting added (en: 'Good morning', es: 'Buenos días').
v0.35.0
2026-05-24
- Mobile + web polish — matches the chrome recipe Knit shipped in Phase 6. Suite top bar is now sticky on mobile (scripture rail no longer scrolls away). Tab bar tap targets enforced at 56px minimum per tab. Main content padding switched from a hard-coded pb-24 to a new .safe-pb-tabbar utility that adds env(safe-area-inset-bottom) so the iOS home indicator is respected on every phone.
- Suggestion FAB is desktop-only now (hidden md:flex), shrunk to 40px gold, opacity 85 → 100 on hover. On phones the same modal opens from a new 'Suggest an enhancement' row in Settings → Help & feedback (joined by User guide and Release notes, which used to live in tiny gray links at the very bottom of the screen). The Send / Cancel buttons inside the modal are now 44px k-btn / k-btn-outline.
- New SuggestionContext provider holds the modal-open state at AppShell scope so any client component can call useSuggestion().open() — that's how Settings hands feedback off to the FAB without a floating button.
- Globals: new utilities .safe-bottom, .safe-pb-tabbar, .scroll-pb-fab, .k-btn / .k-btn-gold / .k-btn-outline (matches Knit's recipe, swap rose for gold). New token --color-glean-ink (#5C4A14) for readable text on gold fills.
- i18n: settings.helpFeedback / settings.suggestEnhancement / settings.suggestEnhancementBody added in English and Spanish.
v0.34.0
2026-05-23
- Removed the Manage Leaders page (and its /api/admin/leaders route + the Settings button that opened it). Glean leaders are now maintained automatically from the suite roles assigned in Gather — a Postgres trigger on gather_user_roles upserts the right glean_leaders row whenever someone gets a Stake Presidency / Stake Clerk / Bishop role, and removes the row when revoked. Glean keeps reading glean_leaders unchanged, so chat persona / plan access / resource ownership / member access all work exactly as before.
- Role-to-bucket mapping: Stake President + 1st/2nd Counselors → 'stake'; Stake Clerk + Stake Executive Secretary → 'clerk'; Bishop + Bishopric 1st/2nd Counselors → 'bishop' (with ward picked up from the gather assignment). One glean_leaders row per user, highest privilege wins if a user holds multiple qualifying roles.
- One-time backfill ran during the migration: 5 leaders now in glean_leaders (vs the 2 from the manual page) — Celso, Blake, and Vielman picked up their leader status from existing gather role assignments that had never been mirrored over. Settings page now points only to Gather and notes the auto-sync; the 'leaders out of date' message on the Grant Access modal in plan detail now links straight to Gather.
v0.33.0
2026-05-23
- Gather moved out of Glean into its own standalone deployment at https://gathered-admin-neon.vercel.app/gather. /admin/gather and /admin/roles in Glean are now thin redirect pages so old bookmarks still work; the Settings menu links straight to the new host in a new tab. Why: one canonical place to manage user access across all five Gathered apps, with a redesigned row + side-panel UI (app access tiles, super-admin + per-app admin toggles, suite roles filterable into stake/ward groups with ward picker, Tidings cross-project users, Suggestions inbox — all in one page).
- Lookup-table hardening: enabled RLS on `glean_calling_role_mappings` (was anon-readable). Authenticated SELECT, super-admin write; edge functions use the service role so the calling→role auto-grant sync is unaffected.
v0.32.1
2026-05-22
- Ask Glean now refers leaders to specific training videos by name + URL. The lesson transcripts already landed in 0.32.0 (the 'Read Transcript' accordions inline in each lesson), but the embedded Brightcove video URLs themselves weren't being pulled. The fetch script now walks each lesson's multimedia blocks, extracts the iframe `src`, normalizes protocol-relative URLs, and pairs each video with the heading immediately before it and the transcript immediately after.
- Result: 12 videos indexed across lessons 2, 3, 6, 8, and 15 — including 'See Others as the Savior Sees Them' / 'Address Immediate Needs' / 'Build Self-Reliance' (Lesson 2), Abie Turay's and Rosita Surio's self-reliance stories (Lesson 3), 'A Mother Left on Her Own' and 'Achieving Her Potential' (Lesson 6), the three-step Self-Reliance Plan walkthrough (Lesson 8), and the 'Empathize and Seek to Understand' / 'Consider Resources' pair (Lesson 15). Each is in the prompt with its Brightcove player URL and full transcript.
- Persona updated: when a specific video illustrates the answer, the assistant now names it ("Watch 'Address Immediate Needs' in Lesson 2") and emits the video URL on its own "Video:" line — same as Source for lesson links.
- The video index lives in the same cached 1-hour system block as the lesson text, so the additional ~12 video records cost nothing per turn after the first.
v0.32.0
2026-05-22
- Ask Glean now grounds answers in the Church's official **Welfare & Self-Reliance training** alongside Handbook 22. Pulled all 17 lessons of *Provide for My Saints* — the full e-learning course at broadcast.lds.org — and bundled them as a new cached system block. The persona was updated so the model names the lesson ("Lesson 2: When I meet with someone in need…") and cites the canonical lesson URL on a Source line when its answer leans on training content.
- Topics now covered with direct lesson links: how Jesus ministered to those with temporal needs, what to do/say when a member is in need, helping members embrace self-reliance, leader responsibilities, using the ward council, balancing immediate relief with long-term self-reliance, developing a self-reliance plan, types of assistance, the assistance process, deciding what to provide and how long, ways the Church and community help, government resources, what to do for emotional needs, helping members with emotional challenges, and self-reflection for leaders.
- Implementation: `scripts/fetch-wsrs-training.mjs` fetches each lesson, decodes the JSONP-wrapped or inline-embedded base64 course payload (broadcast.lds.org uses two upstream Rise-Articulate formats side-by-side), and extracts the text into `src/lib/wsrs/training.ts` as `WSRS_LESSONS` + `WSRS_TRAINING_TEXT`. Re-run the script when the church updates the training. ~60 KB of lesson content; sits in its own ephemeral 1-hour prompt-cache block so it's reused across every leader question without re-billing each turn.
- Why this matters: bishops asking "how should I approach a self-reliance interview?" or "what should I say when someone needs rent help?" now get answers that point straight at the lesson the Church wrote for exactly that situation, with the link.
v0.31.2
2026-05-22
- Stake renamed. `glean_stakes.name` was seeded as "Hyde Park Stake" — that's three of the wards, not the stake. The real stake is the **Chicago Illinois Stake**. Migration `0019_rename_stake.sql` updates the live row; the seed in `0003_seed.sql` was corrected too so a fresh install gets the right name.
- Affects the Plans-tab subtitle for Stake President / Stake Clerk (which displays the stake name) and anywhere else the stake name appears.
v0.31.1
2026-05-22
- The plan-body visibility predicate (`glean_can_see_plan_body`) now recognizes the plan's author. A stake-level leader who starts a plan for someone in a ward they don't directly lead used to be locked out of the plan they just created — the predicate only checked welfare-super / member-self / ward-bishop / ward-leader-v2 / explicit-grant, and a stake user's `glean_leaders` row matches none of those. After this migration, the author always sees their own plan.
- Author can now write too. The narrative / goals / actions / resources write policies were widened to allow the plan author alongside ward_leader_v2 / welfare_super. Comments-read was widened so the author sees leader-only notes (members still don't).
- Schema: new helper `glean_is_plan_author(plan_id)` SECURITY DEFINER + STABLE, plus drop/recreate of the four write policies and the comments-read policy. `0018_plan_author_visibility.sql`.
- Symptom this fixes: when a stake leader started a plan and then tried to **Request access** to it from the gated card, the RPC returned "No bishop or author on file to notify" — the only candidate recipient (the plan's author) was the requester themselves, and Hyde Park 1st in particular has 0 rows in `glean_leaders` for the bishop role. After this fix the gated card no longer renders for the author, so they don't hit the request flow at all on their own plans.
- Heads up on the data side: Hyde Park 1st (and likely other wards) has 0 bishops registered in `glean_leaders`. The auto-grant pipeline from Tidings → Glean (v0.22.x) hasn't populated bishops there. Until that's filled in, requesting access on a plan in those wards will only fan out to the plan author.
v0.31.0
2026-05-22
- The "Plan access required" card on /members/[id] is now actionable. It identifies the plan owner by name and role, lists the ward's bishop, and offers a one-tap **Request access** button — calling the same `glean_request_plan_access` RPC the search flow already uses. Stake leaders no longer have to chase down who started a plan; the page tells them and lets them ask in-app.
- Access-request notifications grew **Grant** and **Deny** buttons. The recipient (the plan's bishop or the plan author) acts directly from their home Notifications panel. Grant opens the Handbook 22.4.5 member-permission confirm prompt before committing; the prompt mirrors the existing GrantAccessButton wording so the policy lives in one place. Deny marks the notification read and writes an audit-log entry — no return notification, by design (the audit log carries the record without inflating the notification CHECK constraint).
- Schema: `0017_notification_actor.sql` adds `glean_notifications.actor_user_id` (nullable) and rewires `glean_request_plan_access()` to populate it with the requester's uid. Without this column the Grant button can't tell *who* to grant to. Existing rows stay null — only new access requests carry the field.
- Grant uses an upsert against `(plan_id, user_id)` so a second request from the same person can't double-insert. When the request is granted, sibling notifications (when the request fanned out to both bishop and author) are also marked read so the loop closes for everyone who was asked.
v0.30.1
2026-05-22
- User guide page (`/guide`) updated for the Plans tab — replaces the old "From Members, open the member…" instruction with the new search-the-directory flow and adds a `The Plans tab` section explaining role scope and the Start / Open / Request access actions.
- Plans tab header no longer shows a blank subtitle for stake leaders. Stake/clerk users now see the stake name (or "All wards" as a fallback) instead of an empty line where the ward name used to be.
- Pruned orphaned i18n keys left over from the home rewrite in 0.27 and the Plans rename in 0.28: `nav.members`, `home.greetingMorning` / `Afternoon` / `Evening`, `home.aboutHero`, `home.statActive` / `statPending` / `statExpiring`, `home.attention` / `noAttention`, `home.allMembers` / `noMembers`, `home.recent`. Twenty-two entries gone across EN and ES.
- Bookkeeping: `package.json` was stuck at `0.28.1` while the changelog had moved to `0.29.0` and `0.30.0` — version is now back in sync at `0.30.1`.
v0.30.0
2026-05-22
- Glean is now the canonical host of the Gather page. The Steward and Knit copies of /admin/gather have been retired and redirect here. Tidings's GATHER header button also retargeted to point at Glean. Why Glean: it had the most-evolved version — the suite-app filter that hides Duty / Sparkle Pro / Squarecana users, the Remove-from-suite control, and the new Suggestions section. No code changes inside Glean for this release; this is a portfolio-wide consolidation note. Heads up: each app authenticates with its own cookie, so super admins clicking the Gather link from Steward / Knit / Tidings may need to sign in to Glean once.
v0.29.0
2026-05-22
- Gather page (/admin/gather) gained a Suggestions section. It reads from the shared `app_suggestions` table (where the 💡 button on every app posts) and shows a per-app summary — Open / Backlog / Total — with a green **New** badge on any app that has unprocessed suggestions. Below the summary, each open or backlog suggestion lists in full with submitter, date, and source page URL. Three buttons per item: **Add to backlog**, **Mark complete**, **Decline**. Acting on a suggestion removes it from the view (completed or declined items are filtered out). Backed by a new `gather_set_suggestion_status` RPC locked to super admins.
v0.28.1
2026-05-22
- Desktop sidebar nav (AppShell) now reads **Plans** with the document icon. v0.28.0 only relabeled the mobile TabBar — the desktop sidebar still had `nav.members`, which is what shows on the left at md+ widths.
v0.28.0
2026-05-22
- The Members tab is now the Plans tab. The list shows only members with an *active* plan (any status except `expired`), and what shows is scoped by role: Stake President / Stake Clerk see every active plan in the stake via `glean_plans_roster()` (member + ward + status, no body); Bishop sees every active plan in his ward; EQ / RS / other ward leaders see only the plans they own (`leader_id = me`) **or** plans they've been added to via `glean_plan_access_grants`. This matches the privacy spec from v0.25 — non-bishop ward leaders no longer see every plan in the ward by default.
- Removed the always-on member list. The full Tidings-synced directory is now accessed only through the **Add a member** affordance on the Plans tab. Type a name, see live matches across all wards, and each hit shows one of three actions: **Start a plan** (no existing plan), **Open** (you already have access), or **Request access** (active plan exists, you don't).
- Request-access flow added. Tapping **Request access** calls a new SECURITY DEFINER RPC `glean_request_plan_access(plan_id)` that fans out an `access_requested` notification to the plan's bishop *and* the plan's author (excluding the requester). They see the request on their home Notifications panel and can grant access from the plan's existing PlanAccessPanel.
- Schema: `0014_access_requested_notification.sql` adds the new notification type to the CHECK constraint; `0015_request_plan_access_rpc.sql` adds the RPC (recipients are computed inside the function so the caller can't spoof them); `0016_member_active_plan_summary.sql` adds a SECURITY DEFINER helper that lets non-stake leaders find out whether a directory hit has an active plan they can't see — without exposing the body.
- TabBar relabeled (`nav.members` → `nav.plans`) and got a document/plan icon. The route stays `/members` so existing in-app links and bookmarks keep working.
v0.27.0
2026-05-22
- Home screen is now a role-aware dashboard. Stake President / Stake Clerk land on a stake-wide view: Total plans, Needs approval, Stale (30d+) stat tiles, plus a Plans-by-ward breakdown showing per-ward total / pending / stale counts and the most recent update timestamp. Closes the empty-home-screen gap stake leaders were hitting since 0.25.0 lockdown (ward_id is null for stake-level leaders, so the old `leader && ward` gate left them with just the hero).
- Bishops now see a ward-level dashboard: Total / Needs approval / Stale tiles, a Needs-your-approval section listing every pending plan, and a Plans-in-ward list (most-recent first, up to 12) showing the member, the assigned leader's name, and the relative last-updated time.
- EQ/RS Presidents see a personal dashboard: My plans / Awaiting approval / Stale tiles, an Awaiting-approval section, and a My-plans list of every plan where they're the owner (`leader_id = me`) — each row shows the member, status, and relative last-updated time.
- Hero quote stops getting cut off. The `.glean-wheat-field` linear-gradient held the wheat-cream stop at 80%, which was lightening the bottom of the hero where the Leviticus/Ruth body text lives, making the last lines hard to read. Dark blue now holds to 92%, with the wheat hint compressed to the bottom edge only.
v0.26.0
2026-05-22
- Plan body privacy is now fully enforced at the column level. The four narrative fields (situation / strengths / needs / support_network) have moved off `glean_plans` onto a new `glean_plan_narratives` table that's RLS-gated by `glean_can_see_plan_body()`. Stake admins without explicit grant now get an empty narrative back even if they query `glean_plans` directly — closing the partial leak called out in v0.25.0. Existing plan data was copied over in the same migration; the columns are dropped from `glean_plans`.
- PlanEditor saves to `glean_plan_narratives` (upsert by plan_id). Member detail page joins the narrative on read and flattens it onto the Plan object so downstream code (ResourceLinker context) keeps working unchanged. The Plan type has both a nested `narrative` and the legacy flat accessors — flat ones are now sourced from the join.
- Closes #23 from yesterday's follow-up list. Glean's spreadsheet-mandated rule — "Super Admins should NOT have access to any individual's plan unless added by the plan creator" — is now structurally enforced at every layer.
v0.25.0
2026-05-22
- Plan-body privacy enforcement is on. Per the Gathered User Access spreadsheet (and your confirmation on 2026-05-22): Stake President / Stake Clerk see the plan ROW (member name + status + expiry, which is what the home-page and members-list rendering needs) but NOT plan goals, actions, comments, or resource links unless the plan's creator explicitly adds them to `glean_plan_access_grants`. HC Welfare & Self Reliance has full access. Bishop / ward leaders / plan creator / member-self continue to see the full body.
- On /members/[id], stake-level leaders without explicit access now see a clear "Plan access required" card explaining the rule and pointing them at the plan creator. Members with full access see the unchanged Plan Editor + Resource Linker + Comment Thread + Plan Access panel.
- Implementation: tightened RLS on `glean_plan_goals` / `glean_plan_actions` / `glean_plan_comments` / `glean_plan_resources` to use the `glean_can_see_plan_body()` predicate from v0.21.0. The plan ROW itself (`glean_plans`) stays broadly visible so the home-page roster keeps working.
- Known partial: `glean_plans.situation` / `strengths` / `needs` / `support_network` columns remain readable to stake admins via a direct row query (Postgres RLS can't gate at the column level). Full column-level lockdown requires moving those four columns to a separate `glean_plan_narratives` table — deferred as a schema-migration follow-up.
v0.24.0
2026-05-22
- Adding a member is now directory-first. The form on /members opens with a search box that filters live (debounced 200ms) against the 3,244 synced glean_members. Type two characters, see name + ward + phone/email under it, click to jump straight to that member's plan page. Avoids accidentally duplicating someone who's already in the synced directory. Falls back to the original manual-create form when the person isn't in the directory yet — either via an "Add manually" link in the empty state, or by clicking "Add ‘NAME’ manually" from the no-matches result row.
- When the leader is scoped to a single ward, the search auto-filters to that ward; stake-level leaders see all wards.
v0.23.0
2026-05-22
- Weekly Tidings → Glean member sync now runs automatically. New `pg_cron` job (`glean-sync-tidings-members-weekly`, Mondays 12:00 UTC) fires the `glean-sync-tidings-members` edge function via `pg_net`. Auth: the function URL and a 64-char `INTERNAL_SYNC_SECRET` live in `vault.secrets` on the shared project; the cron command reads both and passes the secret in the Authorization header. The function's existing two-path auth (signed-in super-admin user JWT OR `INTERNAL_SYNC_SECRET`) accepts either. The "Sync from Tidings" button on /admin/roles still works for ad-hoc pulls.
- Fixed: the sync was silently truncating to 1000 contacts because PostgREST caps SETOF/TABLE-returning RPCs at `db-max-rows` (default 1000). The Tidings RPC `gather_tidings_contacts_for_sync` now returns a single `jsonb` array (via `jsonb_agg`), which isn't a result set so the cap doesn't apply. After the fix the cron pulled all 3,244 contacts into `glean_members`. (Same fix applies to the Knit sync, which uses the same Tidings RPC.)
v0.22.1
2026-05-22
- Sync from Tidings now also auto-grants Glean access by calling. After the contacts upsert, every synced member with a non-empty `callings` array and a matching `auth.users` account gets the right `gather_user_roles` entry. Mapping covers what the spreadsheet asks for: Bishop / Bishopric 1st Counselor / Bishopric 2nd Counselor, EQ Presidency (president, counselors, secretary), RS Presidency (same), and Welfare Specialist. EQ + RS Presidency map to `ward_org_presidency`; Welfare Specialist maps to `ward_council`. The picker patterns are stored in a new `glean_calling_role_mappings` table you can edit if a calling phrasing slips through (e.g., add a Spanish-language variant).
- Result toast on /admin/roles now includes the auto-grant counts: "…Auto-granted 3 role(s) from callings (5 already held; 47 no account yet)." "No account yet" means we recognized the calling and the email but the person hasn't signed in to the suite yet — the next sync after they do will pick them up automatically.
- Anti-pattern handling avoids false positives: rule for `bishop` carries `anti_pattern: '%counselor%'` so a calling like "Bishop's Counselor" doesn't grant the `bishop` role.
v0.22.0
2026-05-22
- /admin/roles now has a "Sync from Tidings" button. Pulls every active contact out of the Tidings directory (`gather_tidings_contacts_for_sync` RPC, service-role) and upserts into `glean_members` with their phone, email, ward, and current callings. Safe to re-run — keyed by `tidings_contact_id`, no duplicates. Surface reports counts: inserted / updated / skipped (opted-out or blank) / missing-ward.
- Glean schema extended for the sync: `glean_members.tidings_contact_id`, `callings text[]`, `opted_out`, `synced_at`, `sync_source`. New apply function `glean_apply_tidings_member_sync(jsonb)` (service-role only). New ward-name mapping column `glean_wards.tidings_unit_name` since Tidings' unit names ("Hyde Park 1st Ward") don't match Glean's ("Hyde Park 1st") cleanly enough to derive automatically — explicit mapping seeded for all 9 stake wards.
- Weekly cron schedule is NOT wired this release — manual trigger only. The plan picker UI (searchable list of synced members when creating a plan) is also deferred to the next release.
v0.21.1
2026-05-22
- Cross-app role sync: new `gather_grant_role_service` and `gather_revoke_role_service` RPCs on the shared Supabase project, callable only with the service-role JWT. The Tidings project now has a Postgres trigger on `tidings_user_roles` that fires its own edge function (`sync-roles-to-shared`), which uses these service RPCs to mirror role changes up to `gather_user_roles`. Net effect: a role you grant in Tidings' admin UI shows up in Glean's `/admin/roles` (and every other app that consults `gather_user_roles`) within a couple seconds. Sync is fail-soft — if the secret isn't set yet the DB write succeeds locally, the cross-project replication just silently no-ops.
v0.21.0
2026-05-22
- New /admin/roles screen (linked from Settings as "Assign suite roles") lets stake-suite super admins assign any of the 19 Gathered roles to any signed-in user — Stake President, Stake Clerk, the two SP counselors, Stake Executive Secretary, six High Council variants, Community Events Leader, Stake Council, Bishop, the two bishopric counselors, Ward Clerk, Ward Executive Secretary, Ward Council, Ward Organization Presidency, Ward Mission Leader, and Ward Member. A single person can hold multiple roles. Ward-scoped roles take a ward picker; stake-scoped cover the whole stake. Writes go to `gather_user_roles` on the shared Supabase project (the same source of truth Tidings reads), so a role granted here is visible across every Gathered app that consults it.
- DB foundation for plan-body privacy is now in place but NOT yet enforced (deliberate). Adds helper functions — `glean_can_see_plan_body`, `glean_is_bishop_of_ward`, `glean_is_ward_leader_v2`, `glean_is_welfare_super`, `glean_is_stake_admin`, `glean_current_user_has_gather_role` — and the `glean_plans_roster()` SECURITY DEFINER RPC that returns who-has-a-plan + status without exposing situation/strengths/needs/support-network/goals/actions/comments. The plan / goal / action / comment RLS still uses the existing predicate (`glean_is_ward_leader` OR `glean_is_member_self`) so /members/[id] keeps working for stake leaders. The lockdown — SP/Stake Clerk see roster only, body hidden unless added to `glean_plan_access_grants` — ships in a follow-up release once the home + member-detail pages use the roster RPC. `glean_plan_access_grants` now has RLS: insert/delete is gated to HC W&SR, the plan's creator, or the plan's ward bishop.
v0.20.0
2026-05-22
- Gathered suite: shared 19-role catalog (`gather_roles_catalog`) and cross-app role-assignment table (`gather_user_roles`) added to the shared Supabase project. One row per (email, role, ward); a single person can hold multiple roles. Writes gated to existing super-admins via `gather_super_admins`. New RPCs `gather_grant_role`, `gather_revoke_role`, `gather_get_roles`, `gather_user_has_role`, `gather_current_user_has_role`, `gather_current_user_roles` for use by Glean/Knit/Magnify/Steward (Tidings reads cross-Supabase). Catalog seeded with the 19 roles from the Gathered User Access spreadsheet (Stake President through Ward Member). DB-only release; Glean UI changes (assignment screen + plan-access rewrites) coming next.
v0.19.1
2026-05-20
- Suggestion FAB copy trimmed — removed the "Goes straight to Scott." line under the prompt so the modal stays focused on the question itself.
v0.19.0
2026-05-20
- Suggestion FAB added — small gold lightbulb in the bottom-right of every screen (above the mobile tab bar on phones, lower-right on desktop). Tap it to send a free-form idea or friction note. Submissions land in the shared `app_suggestions` table on the Gathered Supabase project and trigger an email to Scott via Resend, so the whole suite (Glean, Steward, Knit, Tidings, Magnify) now feeds one inbox you can triage and mark `in_progress` / `implemented` / `declined`. The submitter's name, email, user id, and the current page URL are captured automatically when signed in; if you're signed out it still works and just records the page.
v0.18.0
2026-05-19
- Navigation between tabs was still sluggish — feedback was that switching from Home → Members → Resources felt like waiting on each page from cold. A focused perf pass cut the round-trip count per tab click by roughly two thirds. (1) getSessionContext now uses auth.getSession() (a local JWT cookie decode) instead of auth.getUser() (a network call to the Supabase auth server). The proxy/middleware already runs getUser() at the edge for every page request, so re-validating inside the page was a redundant round-trip on every navigation. The notifications server actions were switched the same way and now also share the request-cached session instead of fetching their own user. (2) AppSwitcher — the Gathered chrome at the top of the app — used to fire auth.getUser() and a user_apps SELECT on every page mount, so it flashed in late on every nav. It now seeds from a localStorage cache (24h TTL, keyed by user_id) and revalidates in the background, so the chrome paints instantly. The cache is cleared on sign-out so the next sign-in for a different account doesn't show the previous user's app list. (3) Home, Members, and Resources pages now stream via Suspense — the screen shell (hero / header / filter chrome / add-form affordance) paints immediately, and the data-heavy section loads behind a skeleton that matches the real layout so the page doesn't reflow when the rows arrive.
v0.17.3
2026-05-19
- Favicon updated to match the home-screen icon. The old public/favicon.svg still rendered the navy-bg / white-G design from before the brand-color icon refresh, so Chrome's bookmark bar and browser tab were showing the wrong glyph (browsers prefer SVG favicons when available). Replaced with a new favicon.svg that mirrors the current icon — gold (#C9A84C) background with the white wheat stalk.
v0.17.2
2026-05-19
- Tiny cleanup left over from the v0.17.0 EN/ES move: the Home hero still wrapped the brand mark in a flex justify-between row from when the LangToggle sat on the right of the hero. With the toggle now in the suite-wide top bar, the wrapper had a single child and the justify-between was a no-op. Dropped the wrapper and corrected the comment to point at AppShell as the toggle's home. No visible change.
v0.17.1
2026-05-18
- Home-screen / PWA icon redesigned: gold background (matching the Gathered "G" chip) with a large white wheat-stalk replacing the dark-blue "G" letter. Part of the cross-app icon refresh — each app's icon is now its brand color + its glyph. The wheat ties back to Leviticus 19:10, the verse the banner now carries. icon-192.png, icon-512.png, apple-touch-icon.png, and favicon.png all regenerated from public/icon.svg.
v0.17.0
2026-05-18
- Suite consistency pass (3/5): the EN/ES toggle and the scripture banner now share a single persistent strip directly under the Gathered chrome — present on every screen instead of only on per-page headers. The hero LangToggle on Home and the LangToggle in ScreenHeader were both removed in favor of this single canonical location.
- Scripture banner: a slim line carries Glean's namesake passage — “Thou shalt not glean thy vineyard…thou shalt leave them for the poor and the stranger.” (Leviticus 19:10) — so the welfare imperative is one glance away from any screen. Mirrors the pattern Steward established and matches what Magnify, Knit, and Tidings carry.
- Browser tab title locked to just "Glean" (was "Glean — Welfare & Self-Reliance"). The PWA manifest name is also "Glean" now, so the home-screen install label is tight.
- PWA theme color tuned to the Gathered chip — home-screen browser chrome and PWA install background are now Glean wheat-gold (#C9A84C) instead of navy. The icon background still renders dark in the current PNG; the icon redesign lands in a follow-up cross-app pass.
v0.16.0
2026-05-18
- Eight requested polish + admin changes in one push. (1) Home hero now opens with the About-Glean passage instead of a time-of-day greeting — the Leviticus/Ruth allusion is the whole point of the app and 'Good morning' was burying it. (2) About-Glean copy itself expanded to a two-sentence reflection — the law of the harvest, the practice of leaving a corner of every field unharvested for the poor, the stranger, and the widow, and the parallel work of walking alongside families on the path to self-reliance. (3) EN/ES pill toggle now sits in every header (Tidings-style) so language switching no longer requires digging into Settings — dark variant on the home hero, light variant on the white screen headers. (4) Sidebar 'Stake Suite — Magnify · Steward · Tidings · Glean' footer removed; settings About card lost the same line. (5) Stake clerk / presidency can now Edit (change role + ward) and Remove a leader directly from /admin/leaders without rebuilding the row via upsert. PATCH and DELETE handlers added to /api/admin/leaders. (6) /admin/gather: a Remove column lets the stake clerk / president take a user out of every Gathered app in one click — revokes all five suite-app grants and clears super-admin status. The same screen now filters out auth users whose only grants are for non-Gathered apps (Duty, Sparkle Pro, Squarecana, draft-room) — they're real users but not part of this suite. (7) Resource detail: Edit details moved up directly under the resource info, so leaders don't have to scroll past the ward selector and audit log to fix a typo. (8) Home + members performance pass — getSessionContext is now wrapped in React.cache (one auth+leader+member fetch per request instead of one per call site), the queries on both pages select only the columns rendered (5 instead of 9), and getSessionContext / getServerT now run in parallel with the data queries instead of serially. The owned-expiring lookup on home runs alongside the main members fetch instead of after it.
v0.15.5
2026-05-17
- Follow-up to v0.15.4: the max-w-sm/md width regression was still live in production. Adding --container-* tokens alongside the named --spacing-{name} tokens was not enough — Tailwind v4 had already committed to emitting `.max-w-md { max-width: var(--spacing-md) }` at compile time and the later --container-md declaration was ignored. Removed the unused --spacing-{xs,sm,md,lg,xl,2xl} named tokens entirely; nothing in src/ referenced them as utility classes (no p-sm, gap-md, etc.) and they only existed to be hijacked by the v4 spacing-namespace lookup. Verified: built CSS now emits `.max-w-md { max-width: var(--container-md) }` and `.max-w-sm { max-width: var(--container-sm) }`. Add-a-leader dialog, Tidings-user modal, sign-up, forgot-password and reset-password cards now render at their intended widths.
v0.15.4
2026-05-17
- Two visible layout bugs caught during a click-through of every screen. (1) The 'Add a leader' confidentiality dialog on the member-plan page and the 'Add Tidings user' modal in Settings → Manage Gather were both rendering at 8 pixels wide — text wrapped to one word per line. Same root cause hits the sign-up, forgot-password, and reset-password cards at 16 pixels. The shared tokens.css declared an @theme block that REPLACES Tailwind v4's default theme (rather than extending it), which wiped out the default --container-* scale; Tailwind then fell back to --spacing-sm / --spacing-md (8 px / 16 px) for max-w-sm / max-w-md. Re-declared the full v4 default container scale in tokens.css so max-w-sm = 24rem and max-w-md = 28rem the way every Tailwind class string assumes. (2) The plan detail page was rendering an empty white card between Action Steps and Linked Resources for any viewer who isn't the plan's leader, isn't the bishop, and isn't looking at an expiring plan (e.g., a stake-level reviewer reading a pending plan). The PlanStatusActions card now returns null when none of its three role-conditioned buttons apply.
v0.15.3
2026-05-17
- Maintenance pass — no user-visible behavior changes. (1) Sign-up / forgot-password / reset-password pages no longer show the tab bar and sidebar; those gated nav links would have bounced a logged-out user back to /login anyway and the chrome was just visual noise. (2) /resources rejects unknown ?cat= and ?ward= URL parameters now and falls back to 'all' instead of running a no-match Postgres query — protects against malformed share links and accidental typos. (3) Adding a resource now stores the leader's full name as the 'Added by' value when one is on file; previously it always recorded the user's email, which showed an email address on the resource detail page even when the directory had the leader's name. (4) ESLint config was non-functional (Next 16 + FlatCompat circular-JSON crash); swapped to the flat exports of eslint-config-next so 'npm run lint' actually runs and surfaces real issues. Cleared the seven errors that the broken config had been hiding.
v0.15.2
2026-05-06
- Home-screen badge now also fires for the leader who owns an expiring plan, on top of the existing EQ/RS notifications for the same plan. The leader who created or was assigned a plan via glean_plans.leader_id sees a badge for it the moment its status flips to 'expiring' — even if they aren't a bishop, EQ, or RS president. Counts are deduped by plan ID, so a user holding overlapping roles (e.g., EQ in the plan's ward AND owner of the plan) doesn't get double-counted.
v0.15.1
2026-05-06
- Home-screen badge extended to EQ and RS Presidents: the icon now shows a red number badge for plans about to lapse (status 'expiring') in their ward, in addition to the existing pending-approval badge for bishops. A user holding multiple roles across multiple wards (e.g., bishop in one ward, EQ in another) sees the sum across all of them. Banner copy updated to read "when a plan needs your attention".
v0.15.0
2026-05-05
- Home-screen badge notifications: when a plan in your ward is waiting on your bishop approval, a red number badge now appears on the Glean icon on your phone home screen, even when the app is closed. Tap the new "Get a home-screen alert" banner on the home page to enable. iOS only badges installed home-screen apps — add Glean via Safari → Share → Add to Home Screen first.
- Service worker: Glean now ships a service worker that handles incoming push notifications and updates the app badge silently — no notification text, just the badge.
v0.14.1
2026-05-04
- Gathered switcher: Tidings URL corrected to glad-tidings.vercel.app (the previous tidings.vercel.app pointed at someone else's project).
v0.14.0
2026-05-04
- Per-app brand stripe: a 3px gold strip now sits between the Gathered jump bar and the Glean chrome, picking up the same gold used in the switcher's 'G' chip. The brand identity now follows you into the app instead of stopping at the chip.
v0.13.4
2026-05-04
- Gathered switcher: use the canonical short Magnify and Tidings URLs (magnify-eta.vercel.app and tidings.vercel.app) instead of the team-scoped URLs.
v0.13.3
2026-05-04
- Gather admin: Tidings users section upgraded to full CRUD — add via modal, edit role/ward inline, remove with confirmation. Backed by gather_tidings_grant/update/revoke_user RPCs.
- Admin/gather page marked force-dynamic to prevent static prerender without Supabase env vars.
v0.13.2
2026-05-04
- Visual consistency (Wave 6): hero band padding standardized to pt-14 pb-24 across login/signup/forgot/reset, inline minHeight removed. Logo size standardized to 44px. Focus ring switched to ring-2 + glean-primary/15 on all auth inputs. AppSwitcher chrome color moved to --color-switcher-chrome CSS token.
v0.13.1
2026-05-03
- Gathered switcher now navigates the current tab on app switch instead of spawning a new browser tab. Less tab clutter when hopping between apps.
v0.13.0
2026-05-03
- Tidings users now surface on /admin/gather. Pulled from a new gather_tidings_users SECURITY DEFINER RPC on the Tidings Supabase project (Tidings runs on a separate project from the other four apps). Add / edit / remove still happens inside Tidings via a 'Manage in Tidings ↗' link. Requires NEXT_PUBLIC_GATHER_TIDINGS_SUPABASE_ANON_KEY in Vercel.
v0.12.0
2026-05-03
- i18n: every label and helper string on /login (mode toggle + password labels), /signup, /forgot-password, and /reset-password is now wired through translations.ts with full English and Spanish coverage. Spanish-locale users get fully translated auth pages.
- A11y: every input and primary button on the new auth pages now meets the design system's 44×44 minimum tap target.
v0.11.0
2026-05-03
- Email + password sign-in: /login now has a tab toggle between 'Email link' (the existing magic-link flow) and 'Password' (new). Pick whichever you prefer; both create a session against the same auth.users row.
- Sign up: /signup is now a real form (was an info page) — email + password + confirm. After confirming the email link, ask the Stake President or Stake Clerk to grant you Glean access on /admin/gather.
- Forgot / reset password: new /forgot-password and /reset-password pages backed by Supabase Auth. The Sign-in page links to /forgot-password from the password tab.
- Cross-app grant via RPC: /admin/gather chip toggles now call the gather_grant_app_access / gather_revoke_app_access SECURITY DEFINER RPCs, which idempotently create the per-app profile row when granting access. Granting Glean to a user creates their glean_leaders row with a sane role default; granting Steward creates their steward_user_profiles row already approved; granting Magnify creates their profiles row already approved. Newly-granted users no longer hit a 'no profile yet' gate inside the target app.
v0.10.0
2026-05-03
- Demo role banner: a striped amber strip across the top of every screen with a 'viewing as <role>' picker (Stake President, Stake Clerk, Stake leadership, Bishop, EQ President, RS President, Member). Independent of the existing Settings → demo data toggle (which seeds rows in the database) — the banner just adds the role-switching narrative. Toggle from Settings.
- Settings now surfaces a 'Manage Gather user access' link to /admin/gather for stake-level leaders.
v0.9.0
2026-05-03
- New /signup page explains how to get into Glean for each role — stake leadership are seeded directly, bishops + EQ + RS presidents are added by the Stake President via /admin/gather, and members access plans through their leaders. The Sign-in page links to it as a 'Get access to Glean' callout.
- Footer rebranded from 'Stake Suite' to 'Gather' so it matches the umbrella name used in the cross-app jump bar.
v0.8.0
2026-05-03
- Cross-app user admin: a new /admin/gather screen lets the Stake President or Stake Clerk manage every user's access to the five Gather apps from one table. Toggle the chip for any app to grant or revoke access — it writes to the shared user_apps table that powers the Gathered switcher in every app. Promote / demote a Stake Clerk to super-admin from the same screen.
v0.7.0
2026-05-03
- Gather suite unification: a 'Gathered' jump bar at the very top of the app lets you switch between the five sibling apps (Magnify, Steward, Glean, Tidings, Knit). It only lists apps you have access to — read live from the shared user_apps table — and renders each app as a brand-colored letter chip with a one-line blurb.
- Glean continues to use email magic-link sign-in (no password), so the standard 'forgot password' flow doesn't apply here. Use the magic-link request on the sign-in page if you can't get in.
v0.6.8
2026-05-02
- Fix: 'Pick ward ▾' on the Resources page no longer renders as a vertical column of awkwardly-wrapping pills. Replaced with a native <select> grouped by English / Spanish wards. Familiar UX, works on mobile, doesn't fight the flex-wrap layout.
- When a specific ward is selected the dropdown turns navy to match the other active filter pills; otherwise it reads as 'Pick a specific ward…' so it's obvious nothing is filtered yet.
v0.6.7
2026-05-02
- Fix: pressing Enter while typing a goal or action step now adds the item. Previously the Add button only fired on click. Both forms are real <form> elements with onSubmit handlers, so Enter from the input or the date field works.
- Fix: 'Add a leader' button now always shows for the bishop, plan author, and stake leadership — even when there are no other ward leaders on file yet. Previously the button was hidden behind a 'No leaders to add' label, so a stake clerk creating a plan in a ward without other recorded leaders couldn't see the option at all. The modal now explains the empty case with a deep-link to Settings → Manage leaders.
- Add: Ask Glean lives inside the plan now. The 'Ask Glean to suggest resources' card sits below Linked Resources on every plan page. It pre-loads a prompt seeded with the member's situation, strengths, needs, and support network, then streams a ranked recommendation from the chatbot. Resources mentioned by name in the answer get a one-tap 'Link to plan' button so the leader doesn't have to scroll the directory. The leader can edit the prompt before sending (e.g. add 'Spanish-speaking only' or 'urgent rent assistance').
- Improve: Linked Resources panel is no longer a flat dump of every resource. Tap 'Find a resource' and you get a search box (matches name, address, notes, tags), a row of category chips, and the top 25 matches. Faster to browse and easier to scan than the old long list.
- Data: backfilled plan.leader_id on the existing plan that was created before v0.6.5 — the leader who created it now has plan-author access automatically.
v0.6.6
2026-05-02
- Fix: confidentiality popup now shows the actual handbook quote instead of just a link, and references the correct section (22.4.5, not 22.10). Pulled the verbatim text from the in-app handbook22.ts that Ask Glean is grounded in, so the popup, the audit log explanation, and the chat all cite the same source.
- Popup body now displays the section heading 'Handbook 22.4.5 — Keep Information about Church Assistance Confidential' followed by both relevant paragraphs verbatim, in a gold-bordered callout so it's visually anchored as authority text.
- Footer of the 'Who can see this plan' panel also shows the key sentence ('…the bishop and other leaders generally seek the member's permission to share such information.') with the section attribution.
v0.6.5
2026-05-02
- Privacy: plan visibility tightened. By default a plan is now visible only to (a) the member themselves, (b) the bishop of the ward, (c) stake leadership (clerk / stake presidency), and (d) the leader who authored the plan. EQ presidents, RS presidents, and other ward leaders no longer see plans by default — they must be added explicitly by the bishop or the plan author.
- Add: per-plan transparency view. The member's plan page now has a 'Who can see this plan' panel listing every person with access right now, why they have it (Bishop / Stake / Plan author / Granted by X on date), and a Recent views list showing who actually opened the plan recently (pulled from the existing audit log).
- Add: 'Add a leader' flow. The bishop or plan author can grant access to any other ward leader. A required confirmation popup asks 'Did you receive the member's permission to share this plan with another leader?' — Yes proceeds and records permission_confirmed=true on the grant; No shows a reminder to get permission with a link to Handbook 22.10 — Confidentiality.
- Add: 'Remove' button on each granted leader to revoke access. Both grants and revokes are written to the audit log so the change history is visible.
- Schema: glean_plan_access_grants table + glean_can_see_plan(p_plan) and glean_can_grant_plan_access(p_plan) helper functions. RLS on glean_plans and every plan child table (goals, actions, comments, plan_resources) now goes through glean_can_see_plan. Member-self comments still hide leader_only=true rows.
- Fix: typing in the 'Current Situation' (and any other plan text field) no longer scrolls the page to the bottom on every keystroke. The Field component had been redefined inline on every render, which was unmounting and remounting the textarea — moved it out so React keeps the same node alive.
- Perf: parallelized the member detail page queries (member, plan, resources now load concurrently instead of one after another), and the plan-view audit-log write is now fire-and-forget so it doesn't add to page render time. Added loading.tsx files on /members, /members/[id], /resources, and /resources/[id] so navigation shows an instant spinner instead of a 1–2s blank page.
- When an EQ/RS leader creates a plan, plan.leader_id is now set automatically — previously it was null, which under the new model would have meant the author lost access on their own plan.
v0.6.4
2026-05-02
- Add: plan-lifecycle notifications. When an EQ/RS leader submits a plan, every bishop in that ward gets a notification on their dashboard. When the bishop approves or returns the plan, the leader who authored it gets one back. Wired via a Postgres trigger on glean_plans, so existing client-side status updates keep working unchanged — the trigger fires automatically on status transitions.
- Schema: glean_notifications table with RLS — each user only reads / marks-read / deletes their own notifications. Indexed by (recipient_user_id, read_at, created_at desc) so the dashboard query stays fast.
- UI: Notifications panel on the home dashboard. Unread items render bold with an action-type chip (Submitted / Approved / Returned / Expiring). 'Mark all read' clears the unread state in one tap; tapping a notification opens the member's plan and clicking 'Mark read' clears just that one.
- Add: resource edit form on the resource detail page. Leaders can now update name, category, address, phone, URL, hours, and notes from the same screen — no more 'I think the phone number changed but I have no way to update it.'
- Add: resource edit audit trail. Every save records an entry in glean_audit_log (action='update', entity='resource') with the actor's name and a 'Field: "old" → "new"' summary of which fields changed. Leaders see a 'Recent edits' list at the bottom of every resource page so they can spot when someone changed a phone number, by whom, and when.
- Internals: all resource edits (incl. ward changes from the existing ward selector) now route through a single updateResource server action that does the update + writes the audit row in one place.
v0.6.3
2026-05-02
- Add: 'In adjacent wards' filter on the Resources page. A WC1 leader (or HP1 / W2 / etc.) now sees one extra pill — 'In adjacent wards (HP1, MV)' — that surfaces resources in their ward plus every ward that shares a boundary with theirs. No per-resource fuzzy 'close enough' tagging required.
- Schema: glean_wards.adjacent_ward_ids uuid[] holds each ward's neighbors. Adjacencies were derived from the official 2012/2016 boundary PDFs: in English, WC1↔HP1↔MV↔HP2 (every ward neighbors every other except WC1↔HP2); in Spanish, the chain W2↔C2↔MW↔HP3↔BI plus W2↔MW at the SW corner.
- Chat: Ask Glean now sees the leader's ward AND its adjacent wards in the system prompt, so when nothing in-ward fits it falls back to neighboring-ward resources before going stake-wide. Recommendations stay closer to where the member actually lives.
v0.6.2
2026-05-02
- Add: Spanish ward assignments on resources, using the official 2012/2016 Spanish-overlay ward boundary PDFs for all 5 Spanish wards (Westchester 2nd, Hyde Park 3rd Branch, Blue Island, Midway, Chicago 2nd).
- 54 of 85 resources are now tagged with their Spanish ward — 34 in Chicago 2nd (Loop, West Loop, South Loop, Pilsen, Little Village, Bridgeport, North/South Lawndale, McKinley Park N, Bronzeville N, East Garfield Park, Near North), 15 in Midway (Brighton Park, Stockyards / Back of the Yards, Englewood, Gage Park, Chicago Lawn, West Lawn, Garfield Ridge), 2 in Blue Island (south suburbs + far-south Chicago south of 79th), 2 in Westchester 2nd (Maywood, Melrose Park), and 1 in Hyde Park 3rd Branch (Hyde Park).
- 31 resources stay NULL — stake-wide hotlines (211, NAMI, ABE Illinois, IDHS), Cook-County-wide programs (Greater Chicago Food Depository, Catholic Charities Refugee), multi-location services, and addresses outside the Chicago Illinois Stake (Rogers Park, Albany Park, Uptown, Lincoln Square, Logan Square, West Ridge, Evanston).
- Resource cards now show two pills — 'WC1 EN' (navy) and 'C2 ES' (gold) — when both wards are tagged, so a leader sees the English and Spanish ward of every resource at a glance.
v0.6.1
2026-05-02
- Branding: Glean now has its app icon — navy rounded square with a big white G and a small gold wheat ear at the upper right. Matches the family look used by Magnify, Steward, and Tidings.
- Add: favicon.svg, icon-192.png, icon-512.png, icon-1024.png, apple-touch-icon.png, favicon.png, and manifest.json — installs cleanly to home screen on iOS and Android with the Glean icon.
- Add: scripts/render-icon.mjs — re-renders all PNG variants from the master SVG via sharp. Run with `node scripts/render-icon.mjs` after editing favicon.svg.
v0.6.0
2026-05-02
- Add: ward boundary map upload + accurate ward roster. The Chicago Illinois Stake actually has 4 English wards (Westchester 1st, Hyde Park 1st, Hyde Park 2nd, Moraine Valley) AND 5 Spanish-speaking wards (Westchester 2nd, Hyde Park 3, Blue Island, Midway, Chicago 2nd) covering the same geography. Each address falls in BOTH an English and a Spanish ward; members pick which to attend by language.
- Schema: language column added to glean_wards (en/es). Resources now have english_ward_id AND spanish_ward_id, both nullable.
- Add: 43 of 85 resources mapped to their English ward using the official 2012/2016 stake boundary PDF. The remaining 42 are stake-wide / outside-stake (national hotlines, online services, north-side Chicago addresses in the Wilmette stake, etc.). Spanish ward assignments are still NULL pending the Spanish boundary map.
- UI: Resource cards now show two pills — 'WC1 EN' (navy) and 'HP3 ES' (gold) — when wards are tagged. Resource detail has two dropdowns (English + Spanish) so leaders can tag both.
- Filter: 'Pick ward' panel now groups wards by English / Spanish. 'In my ward' filter matches the leader's ward against either column, so it works for English and Spanish ward leaders alike.
- Chat: Ask Glean now sees both ward labels per resource and the leader's preferred-language ward, so it can recommend in-ward resources for either Spanish or English speakers.
v0.5.0
2026-05-02
- Add: each resource can be tagged with a ward. Detail page shows the current ward (or 'Stake-wide') and lets any leader change it via a dropdown.
- Add: when a resource has no ward set, the detail page links out to the LDS find-a-church tool with the address pre-filled — leaders can look up the ward in 10 seconds and set it.
- Add: Resources list now has a Ward filter row above the category chips: 'All in stake' / 'In my ward' / 'Stake-wide'. Stake clerks and presidency get a 'Pick ward ▾' selector to filter to any ward.
- Add: each resource card shows a small 'In HP1' (etc.) pill when ward_id is set, so you can see at a glance which entries are physically inside ward boundaries.
- Chat: Ask Glean now sees the leader's assigned ward and which ward each resource is in. Persona updated to prefer in-ward resources for ward-leader questions.
- Note: I tried to automate address→ward lookups against the LDS find-a-church endpoint but its API isn't designed for programmatic use without significant reverse engineering. Manual tagging via the new selector is the practical path; the helper link makes it a 10-second-per-resource task.
v0.4.2
2026-05-02
- Cost: Ask Glean now uses 1-hour cache TTL on the handbook + resources blocks (instead of 5-minute). Pays 2x on cache write but stays alive 12x longer — a net win for Glean's bursty usage where leaders ask a few questions in a sitting and then nothing for hours.
- Cost: capped chat answer length at 512 tokens (was 1024). Output tokens are the most expensive line item per token; almost every answer fits comfortably.
v0.4.1
2026-05-02
- Fix: Resources page was returning 0 results because PostgREST couldn't auto-resolve the embedded join on the glean_resource_summaries view. Switched to a separate summary query and merged the data client-side.
v0.4.0
2026-05-02
- Add: Chicago stake resource directory seeded — 85 community resources from the 2025 Chicago Stake Council document, scoped to the Hyde Park (Chicago) stake so other stakes will not see them.
- Add: 3 new resource categories — Legal, Immigration (refugee + immigrant services), Government (benefits) — alongside the existing Food, Housing, Employment, Mental health, Utilities, Education.
- Add: each resource now has a clickable URL on its detail page. Notes for ~30 high-priority resources were enriched from the live websites with services, eligibility, and operating-hours detail.
- Add: Ask Glean now grounds answers in the leader's stake-specific resource directory in addition to Handbook 22. The chat will recommend specific orgs by name with phone and URL when a member needs food, shelter, employment, legal aid, immigration services, or benefits help.
- Caching: stake resources sit in their own cached system block, so the cost of including them in every chat request is amortized across all conversations from the same stake.
v0.3.0
2026-05-01
- Add: responsive AppShell. Desktop now has a navy sidebar with the gold wheat mark, 5 nav links, and active-state highlighting — modeled on the WebDashboard from the original Glean design package.
- Add: mobile keeps the bottom tab bar; desktop hides it in favor of the sidebar. Switch happens at the md breakpoint (768px).
- Add: content column is capped at max-w-3xl on desktop so member lists, plan editors, and forms read naturally without stretching.
- Fix: chat input is now sticky at the bottom of the chat area (above the mobile tab bar, flush with the column on desktop) so it always stays in view.
- Cleanup: dropped the centered-phone-frame layout from v0.2.1 — Glean now reads as a real web app on desktop and a real mobile app on phones, not the same layout shoehorned into both.
v0.2.1
2026-05-01
- Fix: on desktop the whole app now renders inside a centered 480px phone-frame shell (white card on a gray backdrop) so the bottom tab bar and content widths line up. Mobile is unchanged.
- Fix: tab bar and chat input inherit the shell width — no more tiny nav stranded in the middle of a wide page.
- Polish: tab bar icon spacing and label sizing tightened for a consistent height across all five tabs.
v0.2.0
2026-05-01
- Add: demo mode toggle in Settings (stake-level only). Seeds 6 sample members in Hyde Park 1st with plans across all 6 statuses (approved, pending, expiring, expired, draft, none) plus 8 community resources, ratings, comments, and plan↔resource links. Toggle off cleans up safely — only demo-flagged rows are deleted.
- Add: Ask Glean is live. The chat UI now streams responses from Claude (claude-haiku-4-5) grounded in the full text of General Handbook 22 — section 22 Providing for Temporal Needs. Cited answers with section numbers. Prompt caching keeps the per-question cost low.
- Add: glean_settings table for stake-wide app flags.
- Add: is_demo flag on every demo-able table so we can never accidentally delete a real member, plan, or resource.
v0.1.1
2026-05-01
- Fix: tab-bar labels no longer collide on narrow screens (added min-w-0 + truncate, shortened 'Ask Glean' to 'Ask').
- Fix: chat input position respects iPhone home-indicator safe-area, no longer overlaps the tab bar.
- Fix: member detail no longer reserves space for a tab bar that is not rendered.
- Add: server-side language detection via cookie — greeting, section headers, 'View all', 'Add a member', 'Manage leaders' all localize on first paint.
- Add: missing translation keys for home, members, settings.
v0.1.0
2026-05-01
- Initial scaffold: Next.js 15 + Tailwind v4 + Supabase.
- Stake-suite design tokens applied (navy chrome + gold accent).
- Bilingual EN/ES pattern in place via LanguageContext.
- Database schema designed: members, plans, resources, audit log (glean_ prefix on shared Supabase).