Commit Graph

110 Commits

Author SHA1 Message Date
Jakub Zych
54300de94c docs: tags hold topics, the zjazd is meeting_id
The backend materials list shows the zjazd (meeting, by number). The
MCP save and update material tools, the README material example and the
management token test stop modelling a zjazd as a tag, and the README
describes the one-way zjazd tag migration.
2026-11-08 20:30:29 +01:00
Jakub Zych
7cea8ab318 feat: move zjazd tags to the material's meeting
The one-way migration 20261108140000_move_zjazd_tags_to_meetings gives
every material tagged zjazd-N without a meeting meeting N (the lowest
when it has several), never overwrites a meeting_id, logs tags naming a
missing meeting or disagreeing with meeting_id at Warn, and deletes the
exact zjazd-N tags; their links go through ON DELETE CASCADE. Rollback
is a no-op: the backup is the pg_dump taken before migrate.
2026-11-08 20:29:31 +01:00
Jakub Zych
f841e8ed71 feat: extract file text on every attach path and backfill on reindex
- inline and signed uploads queue the text job in their transaction
- the admin form queues it in the save transaction
- detach resyncs the material (its text row goes by cascade)
- bm:materials-reindex backfills missing PDF texts before each sync
2026-11-08 20:16:14 +01:00
Jakub Zych
412821ec56 feat: index the text of attached PDFs
- jz_bm_material_file_texts caches the pdftotext output per file
- the River job jz.bm.extract_material_text extracts and resyncs
- the management multipart attach queues it inside its transaction
- file_texts in the document and a file snippet with its name
2026-11-08 20:11:19 +01:00
Jakub Zych
dd13795e6f feat: search the management list and the MCP material tools
- GET /api/v1/bm/materials takes q: candidates over every material, in
  rank order, with the snippet of the student list; 503 when the engine
  cannot answer
- bm_materials and bm_manage_list_materials take q; under MCP the snippet
  is plain text with ellipses where text was cut
- MCPMaterialPrivacy no longer claims no file text is ever returned
- README documents q, the snippet, the 503, the Search section and
  bm:materials-reindex
2026-11-08 19:53:26 +01:00
Jakub Zych
ffd19342b2 feat: keep the materials index in sync and add bm:materials-reindex
- the materials admin syncs after create and update and removes after
  delete, once the save transaction commits (UseMaterialIndex, set at Boot)
- POST and PUT /api/v1/bm/materials sync after the transaction, DELETE
  removes the document (its statement has no primary key, so no callback)
- bm:materials-reindex [--fresh] [--if-configured] ensures the index and
  syncs every material; it refuses without an engine and runs nightly
  at 04:15 with --if-configured
- TestMaterialSearchAgainstDatabase (Postgres) is written for the final
  verification phase
2026-11-08 19:50:50 +01:00
Jakub Zych
4ffce6e6ac feat: search materials through beachcomber
- Material is a beachcomber Searchable (index jz_bm_materials) in the
  hand-written models/material_search.go; jz.bm requires summercms v0.6.4
- classes.MaterialIndexer asks Typesense for up to 250 candidates with
  body highlights; the app-wide Gate is on only for jz.bm-marked contexts
- GET /_bm/api/v1/materials takes q: candidates are re-gated, counted and
  paged in SQL in rank order, each row with at most one plain snippet
- search failure answers 503 Search is unavailable.; without q the list
  is unchanged
2026-11-08 19:45:46 +01:00
Jakub Zych
f7c400756f build: rebuild the student app (private materials) 2026-11-08 11:58:11 +01:00
Jakub Zych
3346cb6ff6 feat: manage material visibility and shares
The management save/update body takes is_private, author_user_id and
share_user_ids (absent keeps each; a new material gets the caller as
author), and the managed material shows them. New routes PATCH
/materials/{id}/visibility, PUT /materials/{id}/shares and GET /users,
with the MCP tools bm_manage_set_material_visibility,
bm_manage_set_material_shares and bm_manage_list_users. The /bmadmin
form gets the private switch, the author picker and shared_with.
2026-11-08 11:56:14 +01:00
Jakub Zych
418f8240a4 feat: private materials with per-user shares
A material may be private: only its author and the users it is shared
with see it. Every student read (list, detail, course detail and
counters, the checklist linked material, the token twins) goes through
one visibility fragment. Existing materials stay public with no author.

GET/PUT /_bm/api/v1/materials/{id}/access let the author, a material
manager, toggle the flag and pick the users; the first change of an
author-less material makes the caller its author.
2026-11-08 11:52:47 +01:00
Jakub Zych
5ed02ed9f7 build: rebuild the student app (theme switch, print styles) 2026-11-07 20:48:40 +01:00
Jakub Zych
dbd64aca33 build: rebuild the student app (delete a deck, Pilot first) 2026-11-07 19:18:22 +01:00
Jakub Zych
cdc116c145 build: rebuild the student app (mobile tab bar order) 2026-11-07 15:57:44 +01:00
Jakub Zych
89772fa020 build: rebuild the student app (cast status to the casting phone only) 2026-11-07 14:37:26 +01:00
Jakub Zych
ef5155b0ab build: rebuild the student app (cast player mounted before start) 2026-11-07 13:39:01 +01:00
Jakub Zych
2691dca004 build: rebuild the student app (cast keep-awake as in HA) 2026-11-07 13:20:59 +01:00
Jakub Zych
aed08bbe09 build: rebuild the student app (cast keep-awake) 2026-11-07 12:43:13 +01:00
Jakub Zych
7c0f8de31b build: rebuild the student app (cast cover stays down) 2026-11-07 12:34:42 +01:00
Jakub Zych
018cd5537e build: rebuild the student app (cast receiver diagnostics) 2026-11-07 11:57:00 +01:00
Jakub Zych
d6dbcb48bf build: rebuild the student app (cast receiver and cast mode) 2026-11-07 08:35:13 +01:00
Jakub Zych
de1e4624bc build: deck export to PPTX 2026-11-06 15:05:55 +01:00
Jakub Zych
a27a16243d build: robots meta and robots.txt (noindex, Disallow) 2026-11-05 01:59:53 +01:00
Jakub Zych
0dd01855fa build: deck print to PDF, section-slide speaker panels fix 2026-11-03 21:07:15 +01:00
Jakub Zych
a075963c4c Checklisty: procent postępu liczony wg szacowanego czasu 2026-10-30 18:07:36 +01:00
Jakub Zych
9677e58288 fix: answer an empty checklist with an empty items list 2026-10-30 13:36:09 +01:00
Jakub Zych
d894515da1 chore: rebuild the frontend with checklists 2026-10-30 12:41:04 +01:00
Jakub Zych
d7cd5baedf feat: private checklists for zjazd preparation
Per-user checklists with items that may link a course, reading, deadline,
material or own presentation deck. An item with a reading shares the
reading's read mark. Student API routes with token twins, MCP tools,
migrations, tests and README.
2026-10-30 12:41:04 +01:00
Jakub Zych
643f8cbf7c chore: rebuild the frontend with the sztab deck theme 2026-10-30 00:04:25 +01:00
924e6aa0dc feat: signed one-time uploads for material files
- classes/uploads.go: tickets signed with HMAC-SHA256 under the
  jz.bm.upload.v1: label (app.key), 10-minute expiry, the nonce pulled
  from the cache once (duplicated from golem15.presentations on purpose)
- POST /api/v1/bm/materials/{id}/files/upload-url issues the URL with a
  curl example; POST /_bm/api/v1/uploads/{ticket} takes one file part,
  no bearer, throttled per IP and per ticket, user and permission
  re-checked, stored through storeMaterialFile
- bm_manage_create_material_upload; README documents the file routes
2026-10-28 15:10:32 +01:00
ce6ac0a78e test: expect signed one-time material uploads
- TestUploadTicket: HMAC under the jz.bm.upload.v1: label, expiry,
  malformed and foreign tickets, single use through the cache
- TestSignedMaterialUploadRefusesBadTickets, TestCreateMaterialUploadNeedsCaller
- TestRoutes, TestBMMCP and TestManageBucketKey expect the upload-url
  route, the uploads route with its two buckets and the upload tool
- compile-only stubs
2026-10-28 15:07:30 +01:00
93066c63ea feat: attach material files over MCP as base64
- storeMaterialFile: the one attach.Store call of the management API,
  shared by the multipart route and the new inline route
- POST /api/v1/bm/materials/{id}/files/inline: JSON {name, mime?,
  content_base64}, at most 3000000 bytes decoded, body.limit 4300000
- bm_manage_attach_material_file and bm_manage_detach_material_file,
  both warning that material files are public to anyone with the link
2026-10-28 15:03:43 +01:00
a0aaeba0b7 feat: add the BM management MCP tools
- 28 typed tools over /api/v1/bm: list, show, create and update for
  courses and meetings, plus delete for class sessions, readings,
  deadlines and materials (save upserts on title and course)
- inputs mirror Fillable and Rules; enums, lengths and date formats in
  the field descriptions; no seed, me or dry_run tool
- materials accept meeting_id (absent keeps, null clears, must exist)
  and the managed material JSON shows it
- README: MCP tools section
2026-10-28 14:41:30 +01:00
b08d40cba2 test: expect the BM management MCP tools
- 28 typed management tools pinned in TestBMMCP
- body keys are Fillable columns, create inputs require the required
  columns, material save/update require body, source and url
- no seed or me tool, deletes only where the route deletes
- every description names its scope and permission
2026-10-28 14:39:07 +01:00
df42e30034 feat: MCP view of BM answers (absolute links, no material body by default)
- jz.bm.mcp-links on the token twins and the management API: under MCP,
  url and *_url strings starting with a single / get the app base
- material answers under MCP leave the body out unless include_body,
  marking it with body_omitted; write answers never echo it
- jz.bm.manage keys a dispatched call by user
- bm_materials and bm_material student tools
Plain HTTP answers are unchanged.
2026-10-28 14:37:10 +01:00
464c74b80f test: expect the MCP view of BM answers
- viaMCP, includeBody and the material views (no body unless asked)
- jz.bm.mcp-links: absolute url / *_url under MCP only
- jz.bm.manage keyed per user for dispatched calls
- bm_material and bm_materials in the pinned tool list
Compile-only stubs; the tests fail on their assertions.
2026-10-28 14:34:58 +01:00
e106b36a9a feat: add the BM student MCP tools
- token twins of the student API under /_bm/api/v1/token (user.api_token,
  per-user jz.bm.token bucket, a scope on each), from one mountStudent
- pact.HasMCP with the eleven student tools over the twins
- TestBMMCP and TestTokenMirrorRoutes
2026-10-28 14:32:03 +01:00
65a9a683af build: rebuild the student app (connect page) 2026-10-28 14:09:42 +01:00
72043ac85e feat: reserve the MCP paths
/mcp (the MCP endpoint) and /.well-known (the OAuth metadata documents)
join reservedPrefixes, so they answer a plain 404 here instead of the
student app; /connect stays a client route.
2026-10-28 14:09:22 +01:00
0ac83de8b2 test: expect the MCP paths reserved 2026-10-28 14:08:16 +01:00
e22b36e03f chore: require golem15.chat v0.1.3 2026-10-27 11:40:14 +01:00
Jakub Zych
67bc3eb944 build: rebuild the student app (pulpit reading links) 2026-10-27 01:46:33 +01:00
Jakub Zych
ff2f97eb2b feat: materials by zjazd in the student API and admin
The material admin form gets the "Na zjazd" picker, every student
material JSON carries meeting_id, and GET /materials accepts meeting=
inside the published-only scope, so the Pulpit hero can list the
zjazd's materials next to its readings.
2026-10-27 01:44:38 +01:00
Jakub Zych
3241cc9894 feat: zjazd (meeting) on readings and materials
The Pulpit hero lists what to read for the current or next zjazd, so
readings and materials get a nullable meeting_id (FK to jz_bm_meetings,
ON DELETE SET NULL, indexed). The reading admin form gets a "Na zjazd"
picker, the student reading JSON carries meeting_id, and the management
/readings records filter and validate it.
2026-10-27 01:41:48 +01:00
8843e73f98 chore: require golem15.chat v0.1.2 2026-10-26 20:31:54 +01:00
3a7bc46f08 build: rebuild the student app (full-width pages) 2026-10-26 20:08:59 +01:00
35ef575b08 build: rebuild the student app (chat review fixes)
Per-message attachment total, deleted-while-offline messages, nested
code spans in links and /\host site paths.
2026-10-26 19:40:22 +01:00
be3769d75f chore: require golem15.chat v0.1.1 2026-10-26 19:39:54 +01:00
0ff943b6af fix: keep DM participant rows when a user leaves the chat group
The participant sync and the non-member prune now remove only ogólny's
rows. A user taken out of studenci, even briefly, keeps their DMs (the
live membership check denies access while they are out) and gets them
back when re-added, instead of losing them for good.
2026-10-26 19:34:53 +01:00
8b81295458 fix: revoke chat access as soon as a user leaves the chat group
The BM chat context implements golem15.chat's LiveMembership, so every
participant check also requires chat-group membership: a removed user
loses # ogólny, their DMs, uploads, subscriptions and chat:message
delivery at once instead of after the next participant sync.
2026-10-26 19:33:52 +01:00
a840d0ad02 fix: enforce the chat's per-message upload total
jz.bm.chat.max_upload_bytes is now handed to golem15.chat as the total
size of one message's attachments, so the server enforces the limit the
bootstrap advertises.
2026-10-26 19:32:07 +01:00