-
+
{theme.title}
-
+
{theme.description}
@@ -80,49 +101,34 @@ export function ThemeCard({ theme, onUpdate }: ThemeCardProps) {
{theme.source_documents.length} source doc{theme.source_documents.length !== 1 ? 's' : ''}
- {queued} micro-learnings queued for generation
+ {toast && (
+
+ {toast}
)}
{error && (
-
+
{error}
)}
-
-
-
-
+ {!isRejected && (
+
+
+
+ )}
+ {!isPublished && !isRejected && (
+ <>
+
+
+ >
+ )}
)
diff --git a/app/frontend/src/lib/services.ts b/app/frontend/src/lib/services.ts
index 4a7d3d4..de7117a 100644
--- a/app/frontend/src/lib/services.ts
+++ b/app/frontend/src/lib/services.ts
@@ -19,16 +19,22 @@ async function handleResponse
(res: Response): Promise {
return res.json() as Promise
}
-export async function postIngest(formData: FormData): Promise<{ jobId: string }> {
+export async function postIngest(payload: {
+ documentId: string
+ filename: string
+ format: 'pdf' | 'md' | 'txt'
+ fileUrl: string
+}): Promise<{ jobId: string }> {
const res = await fetch(`${INGESTION_URL}/ingest`, {
method: 'POST',
- body: formData,
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload),
})
return handleResponse<{ jobId: string }>(res)
}
export async function getIngestionStatus(jobId: string): Promise {
- const res = await fetch(`${INGESTION_URL}/ingest/${encodeURIComponent(jobId)}/status`)
+ const res = await fetch(`${INGESTION_URL}/ingest/status/${encodeURIComponent(jobId)}`)
return handleResponse(res)
}
diff --git a/app/pb_migrations/1779567108_updated_badges.js b/app/pb_migrations/1779567108_updated_badges.js
new file mode 100644
index 0000000..1560152
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_badges.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("5gl7qj7aky6wjl9")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("5gl7qj7aky6wjl9")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_curriculum_versions.js b/app/pb_migrations/1779567108_updated_curriculum_versions.js
new file mode 100644
index 0000000..f9847f6
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_curriculum_versions.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("1cbepol4z1jxb20")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("1cbepol4z1jxb20")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_curriculum_weeks.js b/app/pb_migrations/1779567108_updated_curriculum_weeks.js
new file mode 100644
index 0000000..dbe0997
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_curriculum_weeks.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("9ivwlfc584lp63w")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("9ivwlfc584lp63w")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_employee_badges.js b/app/pb_migrations/1779567108_updated_employee_badges.js
new file mode 100644
index 0000000..f6fd87c
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_employee_badges.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("52xqp11w4t0y68u")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("52xqp11w4t0y68u")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_employee_curriculum_state.js b/app/pb_migrations/1779567108_updated_employee_curriculum_state.js
new file mode 100644
index 0000000..facb6ce
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_employee_curriculum_state.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("516qnoxsmeomkte")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.id != \"\""
+ collection.updateRule = "@request.auth.id = user"
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("516qnoxsmeomkte")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_gamification_profiles.js b/app/pb_migrations/1779567108_updated_gamification_profiles.js
new file mode 100644
index 0000000..7757e67
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_gamification_profiles.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("o9gcrudod9g510u")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("o9gcrudod9g510u")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_micro_learnings.js b/app/pb_migrations/1779567108_updated_micro_learnings.js
new file mode 100644
index 0000000..4e03c72
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_micro_learnings.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("li75ivkr87g3r94")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("li75ivkr87g3r94")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_milestone_cards.js b/app/pb_migrations/1779567108_updated_milestone_cards.js
new file mode 100644
index 0000000..70d9e41
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_milestone_cards.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("ilkfmv9xibmekna")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("ilkfmv9xibmekna")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_session_completions.js b/app/pb_migrations/1779567108_updated_session_completions.js
new file mode 100644
index 0000000..6d5c3be
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_session_completions.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("57kc85afcdkjlje")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.id != \"\""
+ collection.updateRule = ""
+ collection.deleteRule = ""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("57kc85afcdkjlje")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_source_documents.js b/app/pb_migrations/1779567108_updated_source_documents.js
new file mode 100644
index 0000000..538b92e
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_source_documents.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("0lr0nf3rzh5tdq3")
+
+ collection.listRule = "@request.auth.role = \"admin\""
+ collection.viewRule = "@request.auth.role = \"admin\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("0lr0nf3rzh5tdq3")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_themes.js b/app/pb_migrations/1779567108_updated_themes.js
new file mode 100644
index 0000000..e836e2f
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_themes.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("bm117d8jhn68xqr")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("bm117d8jhn68xqr")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/pb_migrations/1779567108_updated_topics.js b/app/pb_migrations/1779567108_updated_topics.js
new file mode 100644
index 0000000..1c896ec
--- /dev/null
+++ b/app/pb_migrations/1779567108_updated_topics.js
@@ -0,0 +1,24 @@
+///
+migrate((db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("1ixwljuo2xqxcqj")
+
+ collection.listRule = "@request.auth.id != \"\""
+ collection.viewRule = "@request.auth.id != \"\""
+ collection.createRule = "@request.auth.role = \"admin\""
+ collection.updateRule = "@request.auth.role = \"admin\""
+ collection.deleteRule = "@request.auth.role = \"admin\""
+
+ return dao.saveCollection(collection)
+}, (db) => {
+ const dao = new Dao(db)
+ const collection = dao.findCollectionByNameOrId("1ixwljuo2xqxcqj")
+
+ collection.listRule = null
+ collection.viewRule = null
+ collection.createRule = null
+ collection.updateRule = null
+ collection.deleteRule = null
+
+ return dao.saveCollection(collection)
+})
diff --git a/app/services/ingestion/package-lock.json b/app/services/ingestion/package-lock.json
index f598039..33785c1 100644
--- a/app/services/ingestion/package-lock.json
+++ b/app/services/ingestion/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@anthropic-ai/sdk": "^0.24",
+ "@fastify/cors": "^9.0.1",
"@qdrant/js-client-rest": "^1.9",
"fastify": "^4",
"openai": "^4",
@@ -511,6 +512,16 @@
"fast-uri": "^2.0.0"
}
},
+ "node_modules/@fastify/cors": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz",
+ "integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==",
+ "license": "MIT",
+ "dependencies": {
+ "fastify-plugin": "^4.0.0",
+ "mnemonist": "0.39.6"
+ }
+ },
"node_modules/@fastify/error": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz",
@@ -1067,6 +1078,12 @@
"toad-cache": "^3.3.0"
}
},
+ "node_modules/fastify-plugin": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz",
+ "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==",
+ "license": "MIT"
+ },
"node_modules/fastq": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
@@ -1375,6 +1392,15 @@
"node": ">= 0.6"
}
},
+ "node_modules/mnemonist": {
+ "version": "0.39.6",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz",
+ "integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==",
+ "license": "MIT",
+ "dependencies": {
+ "obliterator": "^2.0.1"
+ }
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -1427,6 +1453,12 @@
}
}
},
+ "node_modules/obliterator": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz",
+ "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==",
+ "license": "MIT"
+ },
"node_modules/on-exit-leak-free": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
diff --git a/app/services/ingestion/package.json b/app/services/ingestion/package.json
index 2bd7a51..73a1d1a 100644
--- a/app/services/ingestion/package.json
+++ b/app/services/ingestion/package.json
@@ -8,10 +8,12 @@
"build": "tsc",
"start": "node dist/index.js",
"migrate": "tsx src/migrations/001_initial_schema.ts",
- "migrate:qdrant": "tsx src/migrations/002_qdrant_setup.ts"
+ "migrate:qdrant": "tsx src/migrations/002_qdrant_setup.ts",
+ "migrate:rules": "tsx src/migrations/003_access_rules.ts"
},
"dependencies": {
"@anthropic-ai/sdk": "^0.24",
+ "@fastify/cors": "^9.0.1",
"@qdrant/js-client-rest": "^1.9",
"fastify": "^4",
"openai": "^4",
diff --git a/app/services/ingestion/src/index.ts b/app/services/ingestion/src/index.ts
index f0af2ca..929e8a2 100644
--- a/app/services/ingestion/src/index.ts
+++ b/app/services/ingestion/src/index.ts
@@ -1,5 +1,6 @@
import 'dotenv/config';
import Fastify from 'fastify';
+import cors from '@fastify/cors';
import documentRoutes from './routes/documents.js';
const PORT = parseInt(process.env['INGESTION_PORT'] ?? '3001', 10);
@@ -7,6 +8,7 @@ const PORT = parseInt(process.env['INGESTION_PORT'] ?? '3001', 10);
async function start(): Promise {
const app = Fastify({ logger: true });
+ await app.register(cors, { origin: true });
await app.register(documentRoutes);
await app.listen({ port: PORT, host: '0.0.0.0' });
diff --git a/app/services/ingestion/src/jobs/queue.ts b/app/services/ingestion/src/jobs/queue.ts
index b7e6419..c150556 100644
--- a/app/services/ingestion/src/jobs/queue.ts
+++ b/app/services/ingestion/src/jobs/queue.ts
@@ -1,4 +1,7 @@
import { v4 as uuid } from 'uuid';
+import { tmpdir } from 'os';
+import { join } from 'path';
+import { writeFile, unlink } from 'fs/promises';
import { extract } from '../pipeline/extract.js';
import { chunk } from '../pipeline/chunk.js';
import { clean } from '../pipeline/clean.js';
@@ -26,7 +29,8 @@ export function createJob(params: IngestBody): Job {
documentId: params.documentId,
filename: params.filename,
format: params.format,
- filePath: params.filePath,
+ fileUrl: params.fileUrl,
+ filePath: '',
status: 'queued',
progress: { ...DEFAULT_PROGRESS },
error: null,
@@ -62,10 +66,20 @@ async function runPipeline(jobId: string): Promise {
const job = jobs.get(jobId);
if (!job) return;
+ let tempPath: string | null = null;
+
try {
+ // Stage 0: download file from PocketBase to temp dir
+ const res = await fetch(job.fileUrl);
+ if (!res.ok) throw new Error(`Failed to download file: ${res.status}`);
+ const buffer = Buffer.from(await res.arrayBuffer());
+ tempPath = join(tmpdir(), `ingest-${jobId}-${job.filename}`);
+ await writeFile(tempPath, buffer);
+ updateJob(jobId, { filePath: tempPath });
+
// Stage 1: text extraction
updateJob(jobId, { status: 'extracting' });
- const text = await extract(job.filePath, job.format);
+ const text = await extract(tempPath, job.format);
// Stages 2–3: chunking + cleaning
updateJob(jobId, { status: 'chunking' });
@@ -98,5 +112,9 @@ async function runPipeline(jobId: string): Promise {
if (j) {
await markDocumentFailed(j.documentId, reason).catch(() => undefined);
}
+ } finally {
+ if (tempPath) {
+ await unlink(tempPath).catch(() => undefined);
+ }
}
}
diff --git a/app/services/ingestion/src/migrations/003_access_rules.ts b/app/services/ingestion/src/migrations/003_access_rules.ts
new file mode 100644
index 0000000..909656d
--- /dev/null
+++ b/app/services/ingestion/src/migrations/003_access_rules.ts
@@ -0,0 +1,60 @@
+import 'dotenv/config'
+import PocketBase from 'pocketbase'
+
+const POCKETBASE_URL = process.env['POCKETBASE_URL'] ?? ''
+const POCKETBASE_ADMIN_EMAIL = process.env['POCKETBASE_ADMIN_EMAIL'] ?? ''
+const POCKETBASE_ADMIN_PASSWORD = process.env['POCKETBASE_ADMIN_PASSWORD'] ?? ''
+
+if (!POCKETBASE_URL || !POCKETBASE_ADMIN_EMAIL || !POCKETBASE_ADMIN_PASSWORD) {
+ console.error('Missing env vars')
+ process.exit(1)
+}
+
+const AUTH_ANY = '@request.auth.id != ""'
+const AUTH_ADMIN = '@request.auth.role = "admin"'
+const AUTH_OWN = '@request.auth.id = user'
+
+// [listRule, viewRule, createRule, updateRule, deleteRule]
+const RULES: Record = {
+ source_documents: [AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ themes: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ topics: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ micro_learnings: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ curriculum_versions: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ curriculum_weeks: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ employee_curriculum_state: [AUTH_ANY, AUTH_ANY, AUTH_ANY, AUTH_OWN, AUTH_ADMIN],
+ session_completions: [AUTH_ANY, AUTH_ANY, AUTH_ANY, '', ''],
+ gamification_profiles: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ badges: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ employee_badges: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+ milestone_cards: [AUTH_ANY, AUTH_ANY, AUTH_ADMIN, AUTH_ADMIN, AUTH_ADMIN],
+}
+
+async function main() {
+ const pb = new PocketBase(POCKETBASE_URL)
+ await pb.admins.authWithPassword(POCKETBASE_ADMIN_EMAIL, POCKETBASE_ADMIN_PASSWORD)
+
+ const collections = await pb.collections.getFullList()
+
+ for (const col of collections) {
+ const rules = RULES[col.name]
+ if (!rules) continue
+
+ const [listRule, viewRule, createRule, updateRule, deleteRule] = rules
+ await pb.collections.update(col.id, {
+ listRule,
+ viewRule,
+ createRule,
+ updateRule,
+ deleteRule,
+ })
+ console.log(`✓ ${col.name}`)
+ }
+
+ console.log('\nAccess rules applied.')
+}
+
+main().catch((err) => {
+ console.error(err)
+ process.exit(1)
+})
diff --git a/app/services/ingestion/src/routes/documents.ts b/app/services/ingestion/src/routes/documents.ts
index 884a947..68f017b 100644
--- a/app/services/ingestion/src/routes/documents.ts
+++ b/app/services/ingestion/src/routes/documents.ts
@@ -12,7 +12,7 @@ const documentRoutes: FastifyPluginAsync = async (app) => {
return reply.status(202).send({ jobId: job.id, status: job.status });
});
- app.get<{ Params: { jobId: string } }>('/status/:jobId', async (request, reply) => {
+ app.get<{ Params: { jobId: string } }>('/ingest/status/:jobId', async (request, reply) => {
const job = getJob(request.params.jobId);
if (!job) {
return reply.status(404).send({ error: 'Job not found' });
@@ -20,8 +20,11 @@ const documentRoutes: FastifyPluginAsync = async (app) => {
return reply.send({
jobId: job.id,
status: job.status,
- progress: job.progress,
- error: job.error,
+ chunksTotal: job.progress.chunksTotal,
+ chunksEmbedded: job.progress.chunksEmbedded,
+ themesFound: job.progress.themesFound,
+ topicsFound: job.progress.topicsFound,
+ reason: job.error ?? undefined,
});
});
};
diff --git a/app/services/ingestion/src/types.ts b/app/services/ingestion/src/types.ts
index 676dbe8..20bc3d5 100644
--- a/app/services/ingestion/src/types.ts
+++ b/app/services/ingestion/src/types.ts
@@ -125,6 +125,7 @@ export interface Job {
documentId: string;
filename: string;
format: DocumentFormat;
+ fileUrl: string;
filePath: string;
status: JobStatus;
progress: JobProgress;
@@ -141,7 +142,7 @@ export const IngestBodySchema = z.object({
documentId: z.string().min(1),
filename: z.string().min(1),
format: z.enum(['pdf', 'md', 'txt']),
- filePath: z.string().min(1),
+ fileUrl: z.string().url(),
});
export type IngestBody = z.infer;