kanban-dev-webapp/pocketbase/pb_migrations/1789600700_created_activity.js
Dave ba990f0109 feat(schema): all collections + role-scoped API rules on remote PB
- migrations/ documented in pocketbase/pb_migrations/ for local PB
- scripts/setup-remote.ts applies them via admin API to remote PB
- collections: clients, projects, columns, cards, subtasks, comments, activity, settings
- user extension: role (owner|client_manager), client (relation)
- writes: owner only for app collections, superuser-only for activity and settings
2026-09-16 09:41:20 +02:00

87 lines
No EOL
2.5 KiB
JavaScript

/// <reference path="../pb_data/types.d.ts" />
/**
* `activity` — an append-only audit log.
*
* This is not a nice-to-have. Once a client can change priorities and dates
* on the developer's board, "I never agreed to that date" has to be
* answerable from the record. Every client-originated write produces a row.
*
* Nothing updates or deletes activity rows. Both rules stay null forever,
* which in PocketBase means superuser-only.
*/
migrate(
(app) => {
const projects = app.findCollectionByNameOrId("projects");
const cards = app.findCollectionByNameOrId("cards");
const users = app.findCollectionByNameOrId("users");
const collection = new Collection({
name: "activity",
type: "base",
listRule: "@request.auth.id != ''",
viewRule: "@request.auth.id != ''",
createRule: null,
updateRule: null,
deleteRule: null,
fields: [
{
name: "project",
type: "relation",
required: true,
collectionId: projects.id,
cascadeDelete: true,
minSelect: 0,
maxSelect: 1,
},
{
name: "card",
type: "relation",
required: false,
collectionId: cards.id,
cascadeDelete: true,
minSelect: 0,
maxSelect: 1,
},
{
name: "actor",
type: "relation",
required: true,
collectionId: users.id,
cascadeDelete: false,
minSelect: 0,
maxSelect: 1,
},
{
name: "action",
type: "select",
required: true,
maxSelect: 1,
values: [
"card_created",
"card_moved",
"card_updated",
"priority_changed",
"date_changed",
"card_accepted",
"comment_added",
"subtask_toggled",
"card_archived",
],
},
{ name: "field", type: "text", required: false, max: 60 },
{ name: "old_value", type: "text", required: false, max: 2000 },
{ name: "new_value", type: "text", required: false, max: 2000 },
{ name: "created", type: "autodate", onCreate: true, onUpdate: false },
],
indexes: [
"CREATE INDEX idx_activity_card ON activity (card, created)",
"CREATE INDEX idx_activity_project ON activity (project, created)",
],
});
return app.save(collection);
},
(app) => {
return app.delete(app.findCollectionByNameOrId("activity"));
}
);