@semiont/backend 0.4.21 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import winston from 'winston';
3
+ import { recordSubscriberConnect, recordSubscriberDisconnect, withTraceparent, withSpan, recordBusEmit, SpanKind, injectTraceparent, getLogTraceContext } from '@semiont/observability';
3
4
  import { z } from 'zod';
4
5
  import jwt from 'jsonwebtoken';
5
- import { email, userId, googleCredential, RESOURCE_BROADCAST_TYPES, PERSISTED_EVENT_TYPES, EventBus, accessToken, resourceId, jobId, entityType, annotationId, didToAgent, assembleAnnotation, CHANNEL_SCHEMAS, userToDid } from '@semiont/core';
6
+ import { email, userId, googleCredential, EventBus, accessToken, resourceId, CHANNEL_SCHEMAS, userToDid, busLog, getPrimaryMediaType, decodeRepresentation } from '@semiont/core';
6
7
  import { cors } from 'hono/cors';
7
8
  import { serve } from '@hono/node-server';
8
9
  import { Hono } from 'hono';
9
10
  import { swaggerUI } from '@hono/swagger-ui';
10
11
  import { SemiontProject, loadEnvironmentConfig } from '@semiont/core/node';
11
- import { exportBackup, importBackup, readEntityTypesProjection, exportLinkedData, importLinkedData, startMakeMeaning, AnnotationContext, ResourceOperations, ResourceContext } from '@semiont/make-meaning';
12
- import crypto2, { randomUUID } from 'crypto';
12
+ import { exportBackup, importBackup, readEntityTypesProjection, exportLinkedData, importLinkedData, startMakeMeaning, ResourceOperations, ResourceContext } from '@semiont/make-meaning';
13
13
  import { PrismaClient } from '@prisma/client';
14
14
  import { PrismaPg } from '@prisma/adapter-pg';
15
15
  import { setCookie, deleteCookie, getCookie } from 'hono/cookie';
@@ -22,6 +22,7 @@ import { streamSSE } from 'hono/streaming';
22
22
  import * as fs from 'fs';
23
23
  import * as path from 'path';
24
24
  import { fileURLToPath } from 'url';
25
+ import { randomUUID } from 'crypto';
25
26
 
26
27
  var __create = Object.create;
27
28
  var __defProp = Object.defineProperty;
@@ -88,12 +89,14 @@ function createFormat(config2) {
88
89
  return winston.format.combine(
89
90
  winston.format.timestamp(),
90
91
  winston.format.errors({ stack: true }),
92
+ traceContextFormat,
91
93
  winston.format.json()
92
94
  );
93
95
  }
94
96
  return winston.format.combine(
95
97
  winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
96
98
  winston.format.errors({ stack: true }),
99
+ traceContextFormat,
97
100
  winston.format.printf(({ level, message, timestamp, ...meta }) => {
98
101
  const metaStr = Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
99
102
  return `${timestamp} [${level.toUpperCase()}] ${message}${metaStr}`;
@@ -152,9 +155,17 @@ function createChildLogger(context) {
152
155
  function createComponentLogger(component) {
153
156
  return createChildLogger({ component });
154
157
  }
155
- var loggerInstance;
158
+ var traceContextFormat, loggerInstance;
156
159
  var init_logger = __esm({
157
160
  "src/logger.ts"() {
161
+ traceContextFormat = winston.format((info) => {
162
+ const trace = getLogTraceContext();
163
+ if (trace) {
164
+ info.trace_id = trace.trace_id;
165
+ info.span_id = trace.span_id;
166
+ }
167
+ return info;
168
+ })();
158
169
  loggerInstance = null;
159
170
  }
160
171
  });
@@ -267,11 +278,11 @@ var init_jwt = __esm({
267
278
  throw error;
268
279
  }
269
280
  }
270
- static generateMediaToken(resourceId7, userId6) {
271
- const payload = { purpose: "media", sub: resourceId7, userId: userId6 };
281
+ static generateMediaToken(resourceId2, userId2) {
282
+ const payload = { purpose: "media", sub: resourceId2, userId: userId2 };
272
283
  return jwt.sign(payload, this.getSecret(), { expiresIn: "5m" });
273
284
  }
274
- static verifyMediaToken(token, resourceId7) {
285
+ static verifyMediaToken(token, resourceId2) {
275
286
  let decoded;
276
287
  try {
277
288
  decoded = jwt.verify(token, this.getSecret());
@@ -280,10 +291,10 @@ var init_jwt = __esm({
280
291
  throw new Error("Invalid media token");
281
292
  }
282
293
  if (decoded["purpose"] !== "media") throw new Error("Invalid media token");
283
- if (decoded["sub"] !== resourceId7) throw new Error("Media token resource mismatch");
294
+ if (decoded["sub"] !== resourceId2) throw new Error("Media token resource mismatch");
284
295
  }
285
- static isAllowedDomain(email2) {
286
- const parts = email2.split("@");
296
+ static isAllowedDomain(email) {
297
+ const parts = email.split("@");
287
298
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
288
299
  return false;
289
300
  }
@@ -9992,290 +10003,6 @@ function makeMeaningConfigFrom(config2) {
9992
10003
 
9993
10004
  // src/index.ts
9994
10005
  init_logger();
9995
-
9996
- // ../../node_modules/nanoid/url-alphabet/index.js
9997
- var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
9998
-
9999
- // ../../node_modules/nanoid/index.js
10000
- var POOL_SIZE_MULTIPLIER = 128;
10001
- var pool;
10002
- var poolOffset;
10003
- var fillPool = (bytes) => {
10004
- if (!pool || pool.length < bytes) {
10005
- pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER);
10006
- crypto2.randomFillSync(pool);
10007
- poolOffset = 0;
10008
- } else if (poolOffset + bytes > pool.length) {
10009
- crypto2.randomFillSync(pool);
10010
- poolOffset = 0;
10011
- }
10012
- poolOffset += bytes;
10013
- };
10014
- var nanoid = (size = 21) => {
10015
- fillPool(size |= 0);
10016
- let id = "";
10017
- for (let i = poolOffset - size; i < poolOffset; i++) {
10018
- id += urlAlphabet[pool[i] & 63];
10019
- }
10020
- return id;
10021
- };
10022
-
10023
- // src/handlers/job-commands.ts
10024
- init_logger();
10025
- var logger = () => getLogger().child({ component: "job-commands" });
10026
- function parseDidUser(did) {
10027
- const parts = did.split(":");
10028
- const usersIdx = parts.indexOf("users");
10029
- const domain = parts.slice(2, usersIdx).join(":");
10030
- const email2 = decodeURIComponent(parts.slice(usersIdx + 1).join(":"));
10031
- return { userId: did, email: email2, domain };
10032
- }
10033
- function registerJobCommandHandlers(eventBus2, jobQueue) {
10034
- eventBus2.get("job:create").subscribe(async (command) => {
10035
- const { correlationId, jobType, resourceId: resId, params, _userId } = command;
10036
- try {
10037
- if (!_userId || typeof _userId !== "string") {
10038
- throw new Error("_userId is required (injected by bus gateway)");
10039
- }
10040
- const user = parseDidUser(_userId);
10041
- const job = {
10042
- status: "pending",
10043
- metadata: {
10044
- id: jobId(`job-${nanoid()}`),
10045
- type: jobType,
10046
- userId: userId(_userId),
10047
- userName: user.email,
10048
- userEmail: user.email,
10049
- userDomain: user.domain,
10050
- created: (/* @__PURE__ */ new Date()).toISOString(),
10051
- retryCount: 0,
10052
- maxRetries: jobType === "generation" ? 3 : 1
10053
- },
10054
- params: {
10055
- resourceId: resourceId(resId),
10056
- ...params
10057
- }
10058
- };
10059
- const jobParams = job.params;
10060
- if (jobType === "reference-annotation" && jobParams.entityTypes) {
10061
- jobParams.entityTypes = jobParams.entityTypes.map((et) => entityType(et));
10062
- }
10063
- await jobQueue.createJob(job);
10064
- logger().info("Job created via bus", { jobId: job.metadata.id, jobType, correlationId });
10065
- eventBus2.get("job:created").next({
10066
- correlationId,
10067
- response: { jobId: job.metadata.id }
10068
- });
10069
- } catch (error) {
10070
- logger().error("job:create failed", { correlationId, error: error.message });
10071
- eventBus2.get("job:create-failed").next({
10072
- correlationId,
10073
- message: error.message
10074
- });
10075
- }
10076
- });
10077
- eventBus2.get("job:claim").subscribe(async (command) => {
10078
- const { correlationId, jobId: jid } = command;
10079
- try {
10080
- const job = await jobQueue.getJob(jobId(jid));
10081
- if (!job) {
10082
- throw new Error("Job not found");
10083
- }
10084
- if (job.status !== "pending") {
10085
- throw new Error("Job already claimed");
10086
- }
10087
- const runningJob = {
10088
- ...job,
10089
- status: "running",
10090
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
10091
- progress: {}
10092
- };
10093
- await jobQueue.updateJob(runningJob, "pending");
10094
- eventBus2.get("job:claimed").next({
10095
- correlationId,
10096
- response: runningJob
10097
- });
10098
- } catch (error) {
10099
- eventBus2.get("job:claim-failed").next({
10100
- correlationId,
10101
- message: error.message
10102
- });
10103
- }
10104
- });
10105
- }
10106
-
10107
- // src/handlers/annotation-lookups.ts
10108
- init_logger();
10109
- var logger2 = () => getLogger().child({ component: "annotation-lookups" });
10110
- function registerAnnotationLookupHandlers(eventBus2, kb, gatherer) {
10111
- eventBus2.get("browse:annotation-context-requested").subscribe(async (command) => {
10112
- const { correlationId } = command;
10113
- const annId = command.annotationId;
10114
- const resId = command.resourceId;
10115
- const contextBefore = command.contextBefore ?? 100;
10116
- const contextAfter = command.contextAfter ?? 100;
10117
- try {
10118
- const response = await AnnotationContext.getAnnotationContext(
10119
- annotationId(annId),
10120
- resourceId(resId),
10121
- contextBefore,
10122
- contextAfter,
10123
- kb
10124
- );
10125
- eventBus2.get("browse:annotation-context-result").next({
10126
- correlationId,
10127
- response
10128
- });
10129
- } catch (error) {
10130
- logger2().warn("annotation-context failed", { correlationId, error: error.message });
10131
- eventBus2.get("browse:annotation-context-failed").next({
10132
- correlationId,
10133
- message: error.message
10134
- });
10135
- }
10136
- });
10137
- eventBus2.get("gather:summary-requested").subscribe(async (command) => {
10138
- const { correlationId } = command;
10139
- const annId = command.annotationId;
10140
- const resId = command.resourceId;
10141
- try {
10142
- const response = await gatherer.generateAnnotationSummary(
10143
- annotationId(annId),
10144
- resourceId(resId)
10145
- );
10146
- eventBus2.get("gather:summary-result").next({
10147
- correlationId,
10148
- response
10149
- });
10150
- } catch (error) {
10151
- logger2().warn("gather:summary failed", { correlationId, error: error.message });
10152
- eventBus2.get("gather:summary-failed").next({
10153
- correlationId,
10154
- message: error.message
10155
- });
10156
- }
10157
- });
10158
- }
10159
-
10160
- // src/handlers/annotation-assembly.ts
10161
- init_logger();
10162
- var logger3 = () => getLogger().child({ component: "annotation-assembly" });
10163
- function registerAnnotationAssemblyHandler(eventBus2) {
10164
- const inflight = /* @__PURE__ */ new Map();
10165
- eventBus2.get("mark:create-request").subscribe((command) => {
10166
- const { correlationId, resourceId: resId, request, _userId } = command;
10167
- const cid = correlationId;
10168
- try {
10169
- if (!_userId || typeof _userId !== "string") {
10170
- throw new Error("_userId is required (injected by bus gateway)");
10171
- }
10172
- if (!cid) {
10173
- throw new Error("correlationId is required on mark:create-request");
10174
- }
10175
- const agent = didToAgent(_userId);
10176
- const { annotation } = assembleAnnotation(request, agent);
10177
- inflight.set(cid, { annotationId: annotation.id });
10178
- eventBus2.get("mark:create").next({
10179
- correlationId: cid,
10180
- annotation,
10181
- userId: userId(_userId),
10182
- resourceId: resourceId(resId)
10183
- });
10184
- logger3().info("Annotation assembled, awaiting persistence", {
10185
- annotationId: annotation.id,
10186
- correlationId: cid
10187
- });
10188
- } catch (error) {
10189
- logger3().warn("mark:create-request failed during assembly", {
10190
- correlationId: cid,
10191
- error: error.message
10192
- });
10193
- eventBus2.get("mark:create-failed").next({
10194
- correlationId: cid,
10195
- message: error.message
10196
- });
10197
- }
10198
- });
10199
- eventBus2.get("mark:added").subscribe((event) => {
10200
- const cid = event.metadata?.correlationId;
10201
- if (!cid) return;
10202
- const pending = inflight.get(cid);
10203
- if (!pending) return;
10204
- inflight.delete(cid);
10205
- eventBus2.get("mark:create-ok").next({
10206
- correlationId: cid,
10207
- response: { annotationId: pending.annotationId }
10208
- });
10209
- logger3().info("Annotation persisted", { annotationId: pending.annotationId, correlationId: cid });
10210
- });
10211
- eventBus2.get("mark:create-failed").subscribe((event) => {
10212
- const cid = event.correlationId;
10213
- if (!cid || !inflight.has(cid)) return;
10214
- inflight.delete(cid);
10215
- });
10216
- }
10217
-
10218
- // src/handlers/bind-update-body.ts
10219
- init_logger();
10220
- var logger4 = () => getLogger().child({ component: "bind-update-body" });
10221
- function registerBindUpdateBodyHandler(eventBus2) {
10222
- const inflight = /* @__PURE__ */ new Set();
10223
- eventBus2.get("bind:update-body").subscribe((command) => {
10224
- const { correlationId, annotationId: annId, resourceId: resId, operations, _userId } = command;
10225
- const cid = correlationId;
10226
- try {
10227
- if (!_userId || typeof _userId !== "string") {
10228
- throw new Error("_userId is required (injected by bus gateway)");
10229
- }
10230
- if (!cid) {
10231
- throw new Error("correlationId is required on bind:update-body");
10232
- }
10233
- inflight.add(cid);
10234
- eventBus2.get("mark:update-body").next({
10235
- correlationId: cid,
10236
- annotationId: annotationId(annId),
10237
- userId: userId(_userId),
10238
- resourceId: resourceId(resId),
10239
- operations
10240
- });
10241
- logger4().info("Bind update-body forwarded to mark:update-body, awaiting persistence", {
10242
- annotationId: annId,
10243
- correlationId: cid
10244
- });
10245
- } catch (error) {
10246
- logger4().warn("bind:update-body failed before forwarding", {
10247
- correlationId: cid,
10248
- error: error.message
10249
- });
10250
- eventBus2.get("bind:body-update-failed").next({
10251
- correlationId: cid,
10252
- message: error.message
10253
- });
10254
- }
10255
- });
10256
- eventBus2.get("mark:body-updated").subscribe((event) => {
10257
- const cid = event.metadata?.correlationId;
10258
- if (!cid || !inflight.has(cid)) return;
10259
- inflight.delete(cid);
10260
- const annId = event.payload?.annotationId;
10261
- eventBus2.get("bind:body-updated").next({
10262
- correlationId: cid,
10263
- annotationId: annId
10264
- });
10265
- logger4().info("Bind body-updated confirmed", { annotationId: annId, correlationId: cid });
10266
- });
10267
- eventBus2.get("mark:body-update-failed").subscribe((event) => {
10268
- const cid = event.correlationId;
10269
- if (!cid || !inflight.has(cid)) return;
10270
- inflight.delete(cid);
10271
- const message = event.message ?? "Unknown error";
10272
- eventBus2.get("bind:body-update-failed").next({
10273
- correlationId: cid,
10274
- message
10275
- });
10276
- logger4().warn("Bind body-update failed after forwarding", { correlationId: cid, message });
10277
- });
10278
- }
10279
10006
  var rootRouter = new Hono();
10280
10007
  rootRouter.get("/", (c) => {
10281
10008
  const config2 = c.get("config");
@@ -11515,27 +11242,6 @@ var openapi_default = {
11515
11242
  "newItem"
11516
11243
  ]
11517
11244
  },
11518
- BeckonResponse: {
11519
- type: "object",
11520
- properties: {
11521
- participant: {
11522
- type: "string",
11523
- description: "Username or agent identifier that was beckoned"
11524
- },
11525
- resourceId: {
11526
- type: "string",
11527
- description: "Resource the attention was directed at"
11528
- },
11529
- annotationId: {
11530
- type: "string",
11531
- description: "Annotation the attention was directed at (if provided)"
11532
- }
11533
- },
11534
- required: [
11535
- "participant",
11536
- "resourceId"
11537
- ]
11538
- },
11539
11245
  CloneResourceWithTokenResponse: {
11540
11246
  type: "object",
11541
11247
  properties: {
@@ -13637,20 +13343,6 @@ var openapi_default = {
13637
13343
  "operations"
13638
13344
  ]
13639
13345
  },
13640
- UpdateResourceRequest: {
13641
- type: "object",
13642
- properties: {
13643
- entityTypes: {
13644
- type: "array",
13645
- items: {
13646
- type: "string"
13647
- }
13648
- },
13649
- archived: {
13650
- type: "boolean"
13651
- }
13652
- }
13653
- },
13654
13346
  UpdateUserRequest: {
13655
13347
  type: "object",
13656
13348
  properties: {
@@ -13883,6 +13575,10 @@ var openapi_default = {
13883
13575
  type: "object",
13884
13576
  description: "Command payload sent on the bind:update-body bus channel to modify annotation bodies.",
13885
13577
  properties: {
13578
+ _userId: {
13579
+ type: "string",
13580
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
13581
+ },
13886
13582
  correlationId: {
13887
13583
  type: "string",
13888
13584
  description: "Client-supplied id used to match this command to its result event(s) on the events-stream. Generated by the route handler if absent."
@@ -13895,10 +13591,6 @@ var openapi_default = {
13895
13591
  type: "string",
13896
13592
  description: "Branded ResourceId of the resource the annotation belongs to"
13897
13593
  },
13898
- userId: {
13899
- type: "string",
13900
- description: "Branded UserId of the user performing the update"
13901
- },
13902
13594
  operations: {
13903
13595
  type: "array",
13904
13596
  items: {
@@ -14935,10 +14627,11 @@ var openapi_default = {
14935
14627
  type: "object",
14936
14628
  description: "Command to mark a job as complete",
14937
14629
  properties: {
14938
- resourceId: {
14939
- type: "string"
14630
+ _userId: {
14631
+ type: "string",
14632
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
14940
14633
  },
14941
- userId: {
14634
+ resourceId: {
14942
14635
  type: "string"
14943
14636
  },
14944
14637
  jobId: {
@@ -14957,7 +14650,6 @@ var openapi_default = {
14957
14650
  },
14958
14651
  required: [
14959
14652
  "resourceId",
14960
- "userId",
14961
14653
  "jobId",
14962
14654
  "jobType"
14963
14655
  ]
@@ -14966,10 +14658,11 @@ var openapi_default = {
14966
14658
  type: "object",
14967
14659
  description: "Command to mark a job as failed",
14968
14660
  properties: {
14969
- resourceId: {
14970
- type: "string"
14661
+ _userId: {
14662
+ type: "string",
14663
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
14971
14664
  },
14972
- userId: {
14665
+ resourceId: {
14973
14666
  type: "string"
14974
14667
  },
14975
14668
  jobId: {
@@ -14988,7 +14681,6 @@ var openapi_default = {
14988
14681
  },
14989
14682
  required: [
14990
14683
  "resourceId",
14991
- "userId",
14992
14684
  "jobId",
14993
14685
  "jobType",
14994
14686
  "error"
@@ -15136,12 +14828,17 @@ var openapi_default = {
15136
14828
  },
15137
14829
  resourceId: {
15138
14830
  type: "string"
14831
+ },
14832
+ userId: {
14833
+ type: "string",
14834
+ description: "DID of the user who initiated the job (audit)."
15139
14835
  }
15140
14836
  },
15141
14837
  required: [
15142
14838
  "jobId",
15143
14839
  "jobType",
15144
- "resourceId"
14840
+ "resourceId",
14841
+ "userId"
15145
14842
  ]
15146
14843
  },
15147
14844
  JobReferenceAnnotationResult: {
@@ -15171,10 +14868,11 @@ var openapi_default = {
15171
14868
  type: "object",
15172
14869
  description: "Command to report progress on a job",
15173
14870
  properties: {
15174
- resourceId: {
15175
- type: "string"
14871
+ _userId: {
14872
+ type: "string",
14873
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15176
14874
  },
15177
- userId: {
14875
+ resourceId: {
15178
14876
  type: "string"
15179
14877
  },
15180
14878
  jobId: {
@@ -15196,7 +14894,6 @@ var openapi_default = {
15196
14894
  },
15197
14895
  required: [
15198
14896
  "resourceId",
15199
- "userId",
15200
14897
  "jobId",
15201
14898
  "jobType",
15202
14899
  "percentage"
@@ -15229,10 +14926,11 @@ var openapi_default = {
15229
14926
  type: "object",
15230
14927
  description: "Command to start a job",
15231
14928
  properties: {
15232
- resourceId: {
15233
- type: "string"
14929
+ _userId: {
14930
+ type: "string",
14931
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15234
14932
  },
15235
- userId: {
14933
+ resourceId: {
15236
14934
  type: "string"
15237
14935
  },
15238
14936
  jobId: {
@@ -15248,7 +14946,6 @@ var openapi_default = {
15248
14946
  },
15249
14947
  required: [
15250
14948
  "resourceId",
15251
- "userId",
15252
14949
  "jobId",
15253
14950
  "jobType"
15254
14951
  ]
@@ -15316,21 +15013,22 @@ var openapi_default = {
15316
15013
  tag: {
15317
15014
  type: "string"
15318
15015
  },
15319
- userId: {
15320
- type: "string"
15016
+ _userId: {
15017
+ type: "string",
15018
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15321
15019
  }
15322
15020
  },
15323
15021
  required: [
15324
- "tag",
15325
- "userId"
15022
+ "tag"
15326
15023
  ]
15327
15024
  },
15328
15025
  MarkArchiveCommand: {
15329
15026
  type: "object",
15330
15027
  description: "Bus command to archive a resource and optionally remove its file.",
15331
15028
  properties: {
15332
- userId: {
15333
- type: "string"
15029
+ _userId: {
15030
+ type: "string",
15031
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15334
15032
  },
15335
15033
  resourceId: {
15336
15034
  type: "string"
@@ -15427,6 +15125,10 @@ var openapi_default = {
15427
15125
  type: "object",
15428
15126
  description: "Bus command to create an annotation on a resource.",
15429
15127
  properties: {
15128
+ _userId: {
15129
+ type: "string",
15130
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15131
+ },
15430
15132
  correlationId: {
15431
15133
  type: "string",
15432
15134
  description: "Optional correlation id threaded from the originating mark:create-request. Propagated into event metadata by Stower so annotation-assembly can emit mark:create-ok after persistence completes."
@@ -15434,16 +15136,12 @@ var openapi_default = {
15434
15136
  annotation: {
15435
15137
  $ref: "#/components/schemas/Annotation"
15436
15138
  },
15437
- userId: {
15438
- type: "string"
15439
- },
15440
15139
  resourceId: {
15441
15140
  type: "string"
15442
15141
  }
15443
15142
  },
15444
15143
  required: [
15445
15144
  "annotation",
15446
- "userId",
15447
15145
  "resourceId"
15448
15146
  ]
15449
15147
  },
@@ -15483,10 +15181,11 @@ var openapi_default = {
15483
15181
  type: "object",
15484
15182
  description: "Bus command to delete an annotation.",
15485
15183
  properties: {
15486
- annotationId: {
15487
- type: "string"
15184
+ _userId: {
15185
+ type: "string",
15186
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15488
15187
  },
15489
- userId: {
15188
+ annotationId: {
15490
15189
  type: "string"
15491
15190
  },
15492
15191
  resourceId: {
@@ -15653,8 +15352,9 @@ var openapi_default = {
15653
15352
  type: "object",
15654
15353
  description: "Bus command to unarchive a previously archived resource.",
15655
15354
  properties: {
15656
- userId: {
15657
- type: "string"
15355
+ _userId: {
15356
+ type: "string",
15357
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15658
15358
  },
15659
15359
  resourceId: {
15660
15360
  type: "string"
@@ -15671,6 +15371,10 @@ var openapi_default = {
15671
15371
  type: "object",
15672
15372
  description: "Bus command to update an annotation's body with patch operations.",
15673
15373
  properties: {
15374
+ _userId: {
15375
+ type: "string",
15376
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15377
+ },
15674
15378
  correlationId: {
15675
15379
  type: "string",
15676
15380
  description: "Correlation id threaded from the originating route through to event metadata. Lets the events-stream deliver matched results to the client that initiated the bind."
@@ -15678,9 +15382,6 @@ var openapi_default = {
15678
15382
  annotationId: {
15679
15383
  type: "string"
15680
15384
  },
15681
- userId: {
15682
- type: "string"
15683
- },
15684
15385
  resourceId: {
15685
15386
  type: "string"
15686
15387
  },
@@ -15703,7 +15404,6 @@ var openapi_default = {
15703
15404
  },
15704
15405
  required: [
15705
15406
  "annotationId",
15706
- "userId",
15707
15407
  "resourceId",
15708
15408
  "operations"
15709
15409
  ]
@@ -15715,8 +15415,9 @@ var openapi_default = {
15715
15415
  resourceId: {
15716
15416
  type: "string"
15717
15417
  },
15718
- userId: {
15719
- type: "string"
15418
+ _userId: {
15419
+ type: "string",
15420
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15720
15421
  },
15721
15422
  currentEntityTypes: {
15722
15423
  type: "array",
@@ -15733,7 +15434,6 @@ var openapi_default = {
15733
15434
  },
15734
15435
  required: [
15735
15436
  "resourceId",
15736
- "userId",
15737
15437
  "currentEntityTypes",
15738
15438
  "updatedEntityTypes"
15739
15439
  ]
@@ -15946,6 +15646,10 @@ var openapi_default = {
15946
15646
  type: "object",
15947
15647
  description: "Bus command to create a yielded resource in the knowledge base.",
15948
15648
  properties: {
15649
+ _userId: {
15650
+ type: "string",
15651
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15652
+ },
15949
15653
  name: {
15950
15654
  type: "string"
15951
15655
  },
@@ -15961,9 +15665,6 @@ var openapi_default = {
15961
15665
  format: {
15962
15666
  $ref: "#/components/schemas/ContentFormat"
15963
15667
  },
15964
- userId: {
15965
- type: "string"
15966
- },
15967
15668
  language: {
15968
15669
  type: "string"
15969
15670
  },
@@ -16015,8 +15716,7 @@ var openapi_default = {
16015
15716
  "storageUri",
16016
15717
  "contentChecksum",
16017
15718
  "byteSize",
16018
- "format",
16019
- "userId"
15719
+ "format"
16020
15720
  ]
16021
15721
  },
16022
15722
  YieldCreateOk: {
@@ -16051,23 +15751,23 @@ var openapi_default = {
16051
15751
  type: "object",
16052
15752
  description: "Bus command to move (rename) a yielded resource.",
16053
15753
  properties: {
15754
+ _userId: {
15755
+ type: "string",
15756
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15757
+ },
16054
15758
  fromUri: {
16055
15759
  type: "string"
16056
15760
  },
16057
15761
  toUri: {
16058
15762
  type: "string"
16059
15763
  },
16060
- userId: {
16061
- type: "string"
16062
- },
16063
15764
  noGit: {
16064
15765
  type: "boolean"
16065
15766
  }
16066
15767
  },
16067
15768
  required: [
16068
15769
  "fromUri",
16069
- "toUri",
16070
- "userId"
15770
+ "toUri"
16071
15771
  ]
16072
15772
  },
16073
15773
  YieldRequestCommand: {
@@ -16125,6 +15825,10 @@ var openapi_default = {
16125
15825
  type: "object",
16126
15826
  description: "Bus command to update a yielded resource's storage content.",
16127
15827
  properties: {
15828
+ _userId: {
15829
+ type: "string",
15830
+ description: "Authenticated user's DID, injected by the /bus/emit gateway. Clients do not set this."
15831
+ },
16128
15832
  resourceId: {
16129
15833
  type: "string"
16130
15834
  },
@@ -16137,9 +15841,6 @@ var openapi_default = {
16137
15841
  byteSize: {
16138
15842
  type: "integer"
16139
15843
  },
16140
- userId: {
16141
- type: "string"
16142
- },
16143
15844
  noGit: {
16144
15845
  type: "boolean"
16145
15846
  }
@@ -16148,8 +15849,7 @@ var openapi_default = {
16148
15849
  "resourceId",
16149
15850
  "storageUri",
16150
15851
  "contentChecksum",
16151
- "byteSize",
16152
- "userId"
15852
+ "byteSize"
16153
15853
  ]
16154
15854
  },
16155
15855
  YieldUpdateOk: {
@@ -16293,8 +15993,8 @@ function validateRequestBody(schemaName) {
16293
15993
  // src/auth/oauth.ts
16294
15994
  init_jwt();
16295
15995
  var OAuthService = class {
16296
- static async verifyGoogleToken(accessToken3) {
16297
- const response = await fetch(`https://www.googleapis.com/oauth2/v2/userinfo?access_token=${accessToken3}`);
15996
+ static async verifyGoogleToken(accessToken2) {
15997
+ const response = await fetch(`https://www.googleapis.com/oauth2/v2/userinfo?access_token=${accessToken2}`);
16298
15998
  if (!response.ok) {
16299
15999
  throw new Error("Failed to verify Google token");
16300
16000
  }
@@ -16363,8 +16063,8 @@ var OAuthService = class {
16363
16063
  isAdmin: user.isAdmin
16364
16064
  };
16365
16065
  const token = accessToken(JWTService.generateToken(jwtPayload, "1h"));
16366
- const refreshToken2 = JWTService.generateToken(jwtPayload, "30d");
16367
- return { user, token, refreshToken: refreshToken2, isNewUser };
16066
+ const refreshToken = JWTService.generateToken(jwtPayload, "30d");
16067
+ return { user, token, refreshToken, isNewUser };
16368
16068
  }
16369
16069
  static async getUserFromToken(token) {
16370
16070
  const payload = JWTService.verifyToken(token);
@@ -16380,10 +16080,10 @@ var OAuthService = class {
16380
16080
  }
16381
16081
  return user;
16382
16082
  }
16383
- static async acceptTerms(userId6) {
16083
+ static async acceptTerms(userId2) {
16384
16084
  const prisma2 = DatabaseConnection.getClient();
16385
16085
  const user = await prisma2.user.update({
16386
- where: { id: userId6 },
16086
+ where: { id: userId2 },
16387
16087
  data: {
16388
16088
  termsAcceptedAt: /* @__PURE__ */ new Date()
16389
16089
  }
@@ -16396,19 +16096,19 @@ var OAuthService = class {
16396
16096
  init_jwt();
16397
16097
  var MEDIA_TOKEN_PATH = /^\/api\/resources\/([^/]+)$/;
16398
16098
  var authMiddleware = async (c, next) => {
16399
- const logger6 = c.get("logger");
16099
+ const logger2 = c.get("logger");
16400
16100
  if (c.req.method === "GET") {
16401
16101
  const mediaTokenParam = c.req.query("token");
16402
16102
  const match = c.req.path.match(MEDIA_TOKEN_PATH);
16403
- const resourceId7 = match?.[1];
16404
- if (mediaTokenParam && resourceId7) {
16103
+ const resourceId2 = match?.[1];
16104
+ if (mediaTokenParam && resourceId2) {
16405
16105
  try {
16406
- JWTService.verifyMediaToken(mediaTokenParam, resourceId7);
16106
+ JWTService.verifyMediaToken(mediaTokenParam, resourceId2);
16407
16107
  c.set("token", mediaTokenParam);
16408
16108
  await next();
16409
16109
  return;
16410
16110
  } catch (error) {
16411
- logger6.warn("Authentication failed: Invalid media token", {
16111
+ logger2.warn("Authentication failed: Invalid media token", {
16412
16112
  type: "auth_failed",
16413
16113
  reason: "invalid_media_token",
16414
16114
  path: c.req.path,
@@ -16426,7 +16126,7 @@ var authMiddleware = async (c, next) => {
16426
16126
  tokenStr = getCookie(c, "semiont-token");
16427
16127
  }
16428
16128
  if (!tokenStr) {
16429
- logger6.warn("Authentication failed: No token", {
16129
+ logger2.warn("Authentication failed: No token", {
16430
16130
  type: "auth_failed",
16431
16131
  reason: "missing_token",
16432
16132
  path: c.req.path,
@@ -16438,7 +16138,7 @@ var authMiddleware = async (c, next) => {
16438
16138
  const user = await OAuthService.getUserFromToken(accessToken(tokenStr));
16439
16139
  c.set("user", user);
16440
16140
  c.set("token", tokenStr);
16441
- logger6.debug("Authentication successful", {
16141
+ logger2.debug("Authentication successful", {
16442
16142
  type: "auth_success",
16443
16143
  userId: user.id,
16444
16144
  email: user.email,
@@ -16448,7 +16148,7 @@ var authMiddleware = async (c, next) => {
16448
16148
  await next();
16449
16149
  return;
16450
16150
  } catch (error) {
16451
- logger6.warn("Authentication failed: Invalid token", {
16151
+ logger2.warn("Authentication failed: Invalid token", {
16452
16152
  type: "auth_failed",
16453
16153
  reason: "invalid_token",
16454
16154
  path: c.req.path,
@@ -16548,27 +16248,27 @@ authRouter.post(
16548
16248
  async (c) => {
16549
16249
  try {
16550
16250
  const body = c.get("validatedBody");
16551
- const { email: email2, password } = body;
16552
- getRouteLogger2().debug("Password auth attempt", { email: email2 });
16251
+ const { email: email$1, password } = body;
16252
+ getRouteLogger2().debug("Password auth attempt", { email: email$1 });
16553
16253
  const prisma2 = DatabaseConnection.getClient();
16554
16254
  const user = await prisma2.user.findUnique({
16555
- where: { email: email2 }
16255
+ where: { email: email$1 }
16556
16256
  });
16557
16257
  if (!user) {
16558
- getRouteLogger2().debug("Password auth failed: user not found", { email: email2 });
16258
+ getRouteLogger2().debug("Password auth failed: user not found", { email: email$1 });
16559
16259
  return c.json({
16560
16260
  error: "Invalid credentials"
16561
16261
  }, 401);
16562
16262
  }
16563
16263
  getRouteLogger2().debug("User found", createSafeLogContext({
16564
- email: email2,
16264
+ email: email$1,
16565
16265
  provider: user.provider,
16566
16266
  isActive: user.isActive,
16567
16267
  hasPasswordHash: !!user.passwordHash
16568
16268
  }));
16569
16269
  if (user.provider !== "password") {
16570
16270
  getRouteLogger2().debug("Password auth failed: wrong provider", {
16571
- email: email2,
16271
+ email: email$1,
16572
16272
  provider: user.provider
16573
16273
  });
16574
16274
  return c.json({
@@ -16576,25 +16276,25 @@ authRouter.post(
16576
16276
  }, 400);
16577
16277
  }
16578
16278
  if (!user.passwordHash) {
16579
- getRouteLogger2().debug("Password auth failed: no password hash", { email: email2 });
16279
+ getRouteLogger2().debug("Password auth failed: no password hash", { email: email$1 });
16580
16280
  return c.json({
16581
16281
  error: "Password not set for this account"
16582
16282
  }, 400);
16583
16283
  }
16584
16284
  const isValid = await argon2.verify(user.passwordHash, password);
16585
16285
  if (!isValid) {
16586
- getRouteLogger2().debug("Password auth failed: invalid password", { email: email2 });
16286
+ getRouteLogger2().debug("Password auth failed: invalid password", { email: email$1 });
16587
16287
  return c.json({
16588
16288
  error: "Invalid credentials"
16589
16289
  }, 401);
16590
16290
  }
16591
16291
  if (!user.isActive) {
16592
- getRouteLogger2().debug("Password auth failed: inactive account", { email: email2 });
16292
+ getRouteLogger2().debug("Password auth failed: inactive account", { email: email$1 });
16593
16293
  return c.json({
16594
16294
  error: "Account is not active"
16595
16295
  }, 403);
16596
16296
  }
16597
- getRouteLogger2().debug("Password auth successful", { email: email2 });
16297
+ getRouteLogger2().debug("Password auth successful", { email: email$1 });
16598
16298
  const jwtPayload = {
16599
16299
  userId: userId(user.id),
16600
16300
  email: email(user.email),
@@ -16604,7 +16304,7 @@ authRouter.post(
16604
16304
  isAdmin: user.isAdmin
16605
16305
  };
16606
16306
  const token = JWTService.generateToken(jwtPayload, "1h");
16607
- const refreshToken2 = JWTService.generateToken(jwtPayload, "30d");
16307
+ const refreshToken = JWTService.generateToken(jwtPayload, "30d");
16608
16308
  await prisma2.user.update({
16609
16309
  where: { id: user.id },
16610
16310
  data: { lastLogin: /* @__PURE__ */ new Date() }
@@ -16628,7 +16328,7 @@ authRouter.post(
16628
16328
  isAdmin: user.isAdmin
16629
16329
  },
16630
16330
  token,
16631
- refreshToken: refreshToken2,
16331
+ refreshToken,
16632
16332
  isNewUser: false
16633
16333
  };
16634
16334
  return c.json(response, 200);
@@ -16656,7 +16356,7 @@ authRouter.post(
16656
16356
  }, 400);
16657
16357
  }
16658
16358
  const googleUser = await OAuthService.verifyGoogleToken(googleCredential(access_token));
16659
- const { user, token, refreshToken: refreshToken2, isNewUser } = await OAuthService.createOrUpdateUser(googleUser);
16359
+ const { user, token, refreshToken, isNewUser } = await OAuthService.createOrUpdateUser(googleUser);
16660
16360
  setCookie(c, "semiont-token", token, {
16661
16361
  httpOnly: true,
16662
16362
  secure: process.env.NODE_ENV === "production",
@@ -16676,7 +16376,7 @@ authRouter.post(
16676
16376
  isAdmin: user.isAdmin
16677
16377
  },
16678
16378
  token,
16679
- refreshToken: refreshToken2,
16379
+ refreshToken,
16680
16380
  isNewUser
16681
16381
  };
16682
16382
  return c.json(response, 200);
@@ -16696,14 +16396,14 @@ authRouter.post(
16696
16396
  async (c) => {
16697
16397
  getRouteLogger2().debug("Refresh endpoint hit");
16698
16398
  const body = c.get("validatedBody");
16699
- const { refreshToken: refreshToken2 } = body;
16700
- if (!refreshToken2) {
16399
+ const { refreshToken } = body;
16400
+ if (!refreshToken) {
16701
16401
  getRouteLogger2().debug("Refresh endpoint: No refresh token provided");
16702
16402
  return c.json({ error: "Refresh token required" }, 401);
16703
16403
  }
16704
16404
  getRouteLogger2().debug("Refresh endpoint: Attempting to verify token");
16705
16405
  try {
16706
- const payload = JWTService.verifyToken(refreshToken2);
16406
+ const payload = JWTService.verifyToken(refreshToken);
16707
16407
  getRouteLogger2().debug("Refresh endpoint: Token verified", { userId: payload.userId });
16708
16408
  if (!payload.userId) {
16709
16409
  getRouteLogger2().debug("Refresh endpoint: No userId in token payload");
@@ -16724,9 +16424,9 @@ authRouter.post(
16724
16424
  isAdmin: user.isAdmin,
16725
16425
  ...user.name && { name: user.name }
16726
16426
  };
16727
- const accessToken3 = JWTService.generateToken(accessTokenPayload, "1h");
16427
+ const accessToken2 = JWTService.generateToken(accessTokenPayload, "1h");
16728
16428
  const response = {
16729
- access_token: accessToken3
16429
+ access_token: accessToken2
16730
16430
  };
16731
16431
  return c.json(response, 200);
16732
16432
  } catch (error) {
@@ -16788,8 +16488,8 @@ authRouter.get("/api/tokens/mcp-setup", authMiddleware, async (c) => {
16788
16488
  isAdmin: user.isAdmin,
16789
16489
  ...user.name && { name: user.name }
16790
16490
  };
16791
- const refreshToken2 = JWTService.generateToken(tokenPayload, "30d");
16792
- return c.redirect(`${callback}?token=${refreshToken2}`, 302);
16491
+ const refreshToken = JWTService.generateToken(tokenPayload, "30d");
16492
+ return c.redirect(`${callback}?token=${refreshToken}`, 302);
16793
16493
  } catch (error) {
16794
16494
  getRouteLogger2().error("MCP setup error", {
16795
16495
  error: error instanceof Error ? error.message : String(error),
@@ -16809,9 +16509,9 @@ authRouter.post("/api/tokens/mcp-generate", authMiddleware, async (c) => {
16809
16509
  isAdmin: user.isAdmin,
16810
16510
  ...user.name && { name: user.name }
16811
16511
  };
16812
- const refreshToken2 = JWTService.generateToken(tokenPayload, "30d");
16512
+ const refreshToken = JWTService.generateToken(tokenPayload, "30d");
16813
16513
  const response = {
16814
- refresh_token: refreshToken2
16514
+ refresh_token: refreshToken
16815
16515
  };
16816
16516
  return c.json(response, 200);
16817
16517
  } catch (error) {
@@ -17432,8 +17132,6 @@ function deriveStorageUri(name, format) {
17432
17132
  const ext = getExtensionForMimeType(format);
17433
17133
  return `file://${slug}${ext}`;
17434
17134
  }
17435
-
17436
- // src/routes/resources/routes/create.ts
17437
17135
  function registerCreateResource(router) {
17438
17136
  router.post("/resources", async (c) => {
17439
17137
  const user = c.get("user");
@@ -17459,108 +17157,63 @@ function registerCreateResource(router) {
17459
17157
  });
17460
17158
  }
17461
17159
  const format = formatRaw;
17462
- const entityTypes = entityTypesStr ? JSON.parse(entityTypesStr) : [];
17463
- const generator = generatorStr ? JSON.parse(generatorStr) : void 0;
17464
- const generatedFrom = sourceResourceId || sourceAnnotationId ? {
17465
- ...sourceResourceId ? { resourceId: sourceResourceId } : {},
17466
- ...sourceAnnotationId ? { annotationId: sourceAnnotationId } : {}
17467
- } : void 0;
17468
- const arrayBuffer = await file.arrayBuffer();
17469
- const contentBuffer = Buffer.from(arrayBuffer);
17470
- const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17471
- const resolvedUri = storageUri || deriveStorageUri(name, format);
17472
- const stored = await kb.content.store(contentBuffer, resolvedUri);
17473
- const eventBus2 = c.get("eventBus");
17474
- const resourceId7 = await ResourceOperations.createResource(
17475
- {
17476
- name,
17477
- storageUri: resolvedUri,
17478
- contentChecksum: stored.checksum,
17479
- byteSize: stored.byteSize,
17480
- format,
17481
- language: language || void 0,
17482
- entityTypes,
17483
- creationMethod: creationMethod || void 0,
17484
- generatedFrom,
17485
- generationPrompt: generationPrompt || void 0,
17486
- generator,
17487
- isDraft: isDraftStr ? isDraftStr === "true" : void 0
17488
- },
17489
- userId(userToDid(user)),
17490
- eventBus2
17160
+ busLog("PUT", "content", {
17161
+ name,
17162
+ format,
17163
+ storageUri,
17164
+ sizeBytes: file.size
17165
+ });
17166
+ const traceparent = c.req.header("traceparent");
17167
+ const tracestate = c.req.header("tracestate");
17168
+ const carrier = traceparent ? tracestate ? { traceparent, tracestate } : { traceparent } : void 0;
17169
+ const resourceId2 = await withTraceparent(
17170
+ carrier,
17171
+ () => withSpan(
17172
+ "content.put.server",
17173
+ async () => {
17174
+ const entityTypes = entityTypesStr ? JSON.parse(entityTypesStr) : [];
17175
+ const generator = generatorStr ? JSON.parse(generatorStr) : void 0;
17176
+ const generatedFrom = sourceResourceId || sourceAnnotationId ? {
17177
+ ...sourceResourceId ? { resourceId: sourceResourceId } : {},
17178
+ ...sourceAnnotationId ? { annotationId: sourceAnnotationId } : {}
17179
+ } : void 0;
17180
+ const arrayBuffer = await file.arrayBuffer();
17181
+ const contentBuffer = Buffer.from(arrayBuffer);
17182
+ const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17183
+ const resolvedUri = storageUri || deriveStorageUri(name, format);
17184
+ const stored = await kb.content.store(contentBuffer, resolvedUri);
17185
+ const eventBus2 = c.get("eventBus");
17186
+ return ResourceOperations.createResource(
17187
+ {
17188
+ name,
17189
+ storageUri: resolvedUri,
17190
+ contentChecksum: stored.checksum,
17191
+ byteSize: stored.byteSize,
17192
+ format,
17193
+ language: language || void 0,
17194
+ entityTypes,
17195
+ creationMethod: creationMethod || void 0,
17196
+ generatedFrom,
17197
+ generationPrompt: generationPrompt || void 0,
17198
+ generator,
17199
+ isDraft: isDraftStr ? isDraftStr === "true" : void 0
17200
+ },
17201
+ userId(userToDid(user)),
17202
+ eventBus2
17203
+ );
17204
+ },
17205
+ {
17206
+ kind: SpanKind.SERVER,
17207
+ attrs: {
17208
+ "content.format": format,
17209
+ "content.size_bytes": file.size
17210
+ }
17211
+ }
17212
+ )
17491
17213
  );
17492
- return c.json({ resourceId: resourceId7 }, 202);
17214
+ return c.json({ resourceId: resourceId2 }, 202);
17493
17215
  });
17494
17216
  }
17495
- [
17496
- ...PERSISTED_EVENT_TYPES.filter((t) => t !== "mark:entity-type-added"),
17497
- ...RESOURCE_BROADCAST_TYPES
17498
- ];
17499
- var LOCALES = [
17500
- { code: "ar", nativeName: "\u0627\u0644\u0639\u0631\u0628\u064A\u0629", englishName: "Arabic" },
17501
- { code: "bn", nativeName: "\u09AC\u09BE\u0982\u09B2\u09BE", englishName: "Bengali" },
17502
- { code: "cs", nativeName: "\u010Ce\u0161tina", englishName: "Czech" },
17503
- { code: "da", nativeName: "Dansk", englishName: "Danish" },
17504
- { code: "de", nativeName: "Deutsch", englishName: "German" },
17505
- { code: "el", nativeName: "\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC", englishName: "Greek" },
17506
- { code: "en", nativeName: "English", englishName: "English" },
17507
- { code: "es", nativeName: "Espa\xF1ol", englishName: "Spanish" },
17508
- { code: "fa", nativeName: "\u0641\u0627\u0631\u0633\u06CC", englishName: "Persian" },
17509
- { code: "fi", nativeName: "Suomi", englishName: "Finnish" },
17510
- { code: "fr", nativeName: "Fran\xE7ais", englishName: "French" },
17511
- { code: "he", nativeName: "\u05E2\u05D1\u05E8\u05D9\u05EA", englishName: "Hebrew" },
17512
- { code: "hi", nativeName: "\u0939\u093F\u0928\u094D\u0926\u0940", englishName: "Hindi" },
17513
- { code: "id", nativeName: "Bahasa Indonesia", englishName: "Indonesian" },
17514
- { code: "it", nativeName: "Italiano", englishName: "Italian" },
17515
- { code: "ja", nativeName: "\u65E5\u672C\u8A9E", englishName: "Japanese" },
17516
- { code: "ko", nativeName: "\uD55C\uAD6D\uC5B4", englishName: "Korean" },
17517
- { code: "ms", nativeName: "Bahasa Melayu", englishName: "Malay" },
17518
- { code: "nl", nativeName: "Nederlands", englishName: "Dutch" },
17519
- { code: "no", nativeName: "Norsk", englishName: "Norwegian" },
17520
- { code: "pl", nativeName: "Polski", englishName: "Polish" },
17521
- { code: "pt", nativeName: "Portugu\xEAs", englishName: "Portuguese" },
17522
- { code: "ro", nativeName: "Rom\xE2n\u0103", englishName: "Romanian" },
17523
- { code: "sv", nativeName: "Svenska", englishName: "Swedish" },
17524
- { code: "th", nativeName: "\u0E44\u0E17\u0E22", englishName: "Thai" },
17525
- { code: "tr", nativeName: "T\xFCrk\xE7e", englishName: "Turkish" },
17526
- { code: "uk", nativeName: "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430", englishName: "Ukrainian" },
17527
- { code: "vi", nativeName: "Ti\u1EBFng Vi\u1EC7t", englishName: "Vietnamese" },
17528
- { code: "zh", nativeName: "\u4E2D\u6587", englishName: "Chinese" }
17529
- ];
17530
- new Map(
17531
- LOCALES.map((locale) => [locale.code.toLowerCase(), locale])
17532
- );
17533
- function getPrimaryRepresentation(resource) {
17534
- if (!resource?.representations) return void 0;
17535
- const reps = Array.isArray(resource.representations) ? resource.representations : [resource.representations];
17536
- return reps[0];
17537
- }
17538
- function getPrimaryMediaType(resource) {
17539
- return getPrimaryRepresentation(resource)?.mediaType;
17540
- }
17541
- function getNodeEncoding(charset) {
17542
- const normalized = charset.toLowerCase().replace(/[-_]/g, "");
17543
- const charsetMap = {
17544
- "utf8": "utf8",
17545
- "iso88591": "latin1",
17546
- "latin1": "latin1",
17547
- "ascii": "ascii",
17548
- "usascii": "ascii",
17549
- "utf16le": "utf16le",
17550
- "ucs2": "ucs2",
17551
- "binary": "binary",
17552
- "windows1252": "latin1",
17553
- // Windows-1252 is a superset of Latin-1
17554
- "cp1252": "latin1"
17555
- };
17556
- return charsetMap[normalized] || "utf8";
17557
- }
17558
- function decodeRepresentation(buffer, mediaType) {
17559
- const charsetMatch = mediaType.match(/charset=([^\s;]+)/i);
17560
- const charset = (charsetMatch?.[1] || "utf-8").toLowerCase();
17561
- const encoding = getNodeEncoding(charset);
17562
- return buffer.toString(encoding);
17563
- }
17564
17217
 
17565
17218
  // src/utils/event-bus-request.ts
17566
17219
  var import_rxjs = __toESM(require_cjs());
@@ -17594,60 +17247,92 @@ function registerGetResourceUri(router) {
17594
17247
  const { id } = c.req.param();
17595
17248
  let acceptHeader = c.req.header("Accept") || "*/*";
17596
17249
  acceptHeader = acceptHeader.split(",").map((t) => t.trim()).filter((t) => t !== "application/ld+json" && t !== "application/json").join(", ") || "*/*";
17597
- const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17598
- let resource;
17599
- try {
17600
- resource = await ResourceContext.getResourceMetadata(resourceId(id), kb);
17601
- } catch {
17602
- throw new HTTPException(500, { message: "Failed to retrieve resource" });
17603
- }
17604
- if (!resource) throw new HTTPException(404, { message: "Resource not found" });
17605
- if (!resource.storageUri) throw new HTTPException(404, { message: "Resource representation not found" });
17606
- const content = await kb.content.retrieve(resource.storageUri);
17607
- if (!content) throw new HTTPException(404, { message: "Resource representation not found" });
17608
- const mediaType = getPrimaryMediaType(resource);
17609
- c.header("Cache-Control", "public, max-age=31536000, immutable");
17610
- if (mediaType) c.header("Content-Type", mediaType);
17611
- if (mediaType?.startsWith("image/") || mediaType === "application/pdf") {
17612
- return c.newResponse(new Uint8Array(content), 200, { "Content-Type": mediaType });
17613
- }
17614
- return c.text(decodeRepresentation(content, mediaType || "text/plain"));
17250
+ busLog("GET", "content", { resourceId: id, accept: acceptHeader });
17251
+ const traceparent = c.req.header("traceparent");
17252
+ const tracestate = c.req.header("tracestate");
17253
+ const carrier = traceparent ? tracestate ? { traceparent, tracestate } : { traceparent } : void 0;
17254
+ return withTraceparent(
17255
+ carrier,
17256
+ () => withSpan(
17257
+ "content.get.server",
17258
+ async () => {
17259
+ const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17260
+ let resource;
17261
+ try {
17262
+ resource = await ResourceContext.getResourceMetadata(resourceId(id), kb);
17263
+ } catch {
17264
+ throw new HTTPException(500, { message: "Failed to retrieve resource" });
17265
+ }
17266
+ if (!resource) throw new HTTPException(404, { message: "Resource not found" });
17267
+ if (!resource.storageUri) throw new HTTPException(404, { message: "Resource representation not found" });
17268
+ const content = await kb.content.retrieve(resource.storageUri);
17269
+ if (!content) throw new HTTPException(404, { message: "Resource representation not found" });
17270
+ const mediaType = getPrimaryMediaType(resource);
17271
+ c.header("Cache-Control", "public, max-age=31536000, immutable");
17272
+ if (mediaType) c.header("Content-Type", mediaType);
17273
+ if (mediaType?.startsWith("image/") || mediaType === "application/pdf") {
17274
+ return c.newResponse(new Uint8Array(content), 200, { "Content-Type": mediaType });
17275
+ }
17276
+ return c.text(decodeRepresentation(content, mediaType || "text/plain"));
17277
+ },
17278
+ {
17279
+ kind: SpanKind.SERVER,
17280
+ attrs: { "resource.id": id, "http.accept": acceptHeader }
17281
+ }
17282
+ )
17283
+ );
17615
17284
  });
17616
17285
  router.get("/resources/:id", async (c) => {
17617
17286
  const { id } = c.req.param();
17618
17287
  const acceptHeader = c.req.header("Accept") || "application/ld+json";
17619
17288
  if (acceptHeader.includes("text/") || acceptHeader.includes("image/") || acceptHeader.includes("application/pdf")) {
17620
- const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17621
- let resource;
17622
- try {
17623
- resource = await ResourceContext.getResourceMetadata(resourceId(id), kb);
17624
- } catch (error) {
17625
- getRouteLogger3().error("Failed to get resource metadata", {
17626
- resourceId: id,
17627
- error: error instanceof Error ? error.message : String(error),
17628
- stack: error instanceof Error ? error.stack : void 0
17629
- });
17630
- throw new HTTPException(500, { message: "Failed to retrieve resource" });
17631
- }
17632
- if (!resource) {
17633
- throw new HTTPException(404, { message: "Resource not found" });
17634
- }
17635
- if (!resource.storageUri) {
17636
- throw new HTTPException(404, { message: "Resource representation not found" });
17637
- }
17638
- const content = await kb.content.retrieve(resource.storageUri);
17639
- if (!content) {
17640
- throw new HTTPException(404, { message: "Resource representation not found" });
17641
- }
17642
- const mediaType = getPrimaryMediaType(resource);
17643
- if (mediaType) {
17644
- c.header("Content-Type", mediaType);
17645
- }
17646
- if (mediaType?.startsWith("image/") || mediaType === "application/pdf") {
17647
- return c.newResponse(new Uint8Array(content), 200, { "Content-Type": mediaType });
17648
- } else {
17649
- return c.text(decodeRepresentation(content, mediaType || "text/plain"));
17650
- }
17289
+ busLog("GET", "content", { resourceId: id, accept: acceptHeader });
17290
+ const traceparent = c.req.header("traceparent");
17291
+ const tracestate = c.req.header("tracestate");
17292
+ const carrier = traceparent ? tracestate ? { traceparent, tracestate } : { traceparent } : void 0;
17293
+ return withTraceparent(
17294
+ carrier,
17295
+ () => withSpan(
17296
+ "content.get.server",
17297
+ async () => {
17298
+ const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17299
+ let resource;
17300
+ try {
17301
+ resource = await ResourceContext.getResourceMetadata(resourceId(id), kb);
17302
+ } catch (error) {
17303
+ getRouteLogger3().error("Failed to get resource metadata", {
17304
+ resourceId: id,
17305
+ error: error instanceof Error ? error.message : String(error),
17306
+ stack: error instanceof Error ? error.stack : void 0
17307
+ });
17308
+ throw new HTTPException(500, { message: "Failed to retrieve resource" });
17309
+ }
17310
+ if (!resource) {
17311
+ throw new HTTPException(404, { message: "Resource not found" });
17312
+ }
17313
+ if (!resource.storageUri) {
17314
+ throw new HTTPException(404, { message: "Resource representation not found" });
17315
+ }
17316
+ const content = await kb.content.retrieve(resource.storageUri);
17317
+ if (!content) {
17318
+ throw new HTTPException(404, { message: "Resource representation not found" });
17319
+ }
17320
+ const mediaType = getPrimaryMediaType(resource);
17321
+ if (mediaType) {
17322
+ c.header("Content-Type", mediaType);
17323
+ }
17324
+ if (mediaType?.startsWith("image/") || mediaType === "application/pdf") {
17325
+ return c.newResponse(new Uint8Array(content), 200, { "Content-Type": mediaType });
17326
+ } else {
17327
+ return c.text(decodeRepresentation(content, mediaType || "text/plain"));
17328
+ }
17329
+ },
17330
+ {
17331
+ kind: SpanKind.SERVER,
17332
+ attrs: { "resource.id": id, "http.accept": acceptHeader }
17333
+ }
17334
+ )
17335
+ );
17651
17336
  }
17652
17337
  const eventBus2 = c.get("eventBus");
17653
17338
  const correlationId = crypto.randomUUID();
@@ -17674,42 +17359,12 @@ function registerGetResourceUri(router) {
17674
17359
  }
17675
17360
  });
17676
17361
  }
17677
- function registerUpdateResource(router) {
17678
- router.patch(
17679
- "/resources/:id",
17680
- validateRequestBody("UpdateResourceRequest"),
17681
- async (c) => {
17682
- const { id } = c.req.param();
17683
- const body = c.get("validatedBody");
17684
- const user = c.get("user");
17685
- const eventBus2 = c.get("eventBus");
17686
- const { knowledgeSystem: { kb } } = c.get("makeMeaning");
17687
- const doc = await ResourceContext.getResourceMetadata(resourceId(id), kb);
17688
- if (!doc) {
17689
- throw new HTTPException(404, { message: "Resource not found" });
17690
- }
17691
- await ResourceOperations.updateResource(
17692
- {
17693
- resourceId: resourceId(id),
17694
- userId: userId(userToDid(user)),
17695
- currentArchived: doc.archived,
17696
- updatedArchived: body.archived,
17697
- currentEntityTypes: doc.entityTypes,
17698
- updatedEntityTypes: body.entityTypes
17699
- },
17700
- eventBus2
17701
- );
17702
- return c.body(null, 202);
17703
- }
17704
- );
17705
- }
17706
17362
 
17707
17363
  // src/routes/resources/index.ts
17708
17364
  function createResourcesRouter() {
17709
17365
  const resourcesRouter2 = createResourceRouter();
17710
17366
  registerCreateResource(resourcesRouter2);
17711
17367
  registerGetResourceUri(resourcesRouter2);
17712
- registerUpdateResource(resourcesRouter2);
17713
17368
  return resourcesRouter2;
17714
17369
  }
17715
17370
  init_logger();
@@ -17753,6 +17408,8 @@ function createBusRouter(authMiddleware2) {
17753
17408
  const connectionId = crypto.randomUUID();
17754
17409
  let ephemeralCounter = 0;
17755
17410
  const nextEphemeralId = () => makeEphemeralId(connectionId, ++ephemeralCounter);
17411
+ recordSubscriberConnect();
17412
+ stream.onAbort(() => recordSubscriberDisconnect());
17756
17413
  const lastDeliveredSeq = /* @__PURE__ */ new Map();
17757
17414
  const writeBusEvent = async (channel, payload, eventScope) => {
17758
17415
  const seq = extractSequence(payload);
@@ -17765,7 +17422,11 @@ function createBusRouter(authMiddleware2) {
17765
17422
  } else {
17766
17423
  id = nextEphemeralId();
17767
17424
  }
17425
+ if (payload && typeof payload === "object") {
17426
+ injectTraceparent(payload);
17427
+ }
17768
17428
  const data = eventScope ? JSON.stringify({ channel, payload, scope: eventScope }) : JSON.stringify({ channel, payload });
17429
+ busLog("SSE", channel, payload, eventScope);
17769
17430
  await stream.writeSSE({ event: "bus-event", data, id }).catch(() => {
17770
17431
  });
17771
17432
  };
@@ -17880,10 +17541,30 @@ function createBusRouter(authMiddleware2) {
17880
17541
  if (user) {
17881
17542
  payload._userId = userToDid(user);
17882
17543
  }
17883
- const bus = scope ? eventBus2.scope(scope) : eventBus2;
17884
- const subject = bus.get(channel);
17885
- subject.next(payload);
17886
- getBusLogger().info("emit", { channel, scope, correlationId: payload.correlationId });
17544
+ const traceparent = c.req.header("traceparent");
17545
+ const tracestate = c.req.header("tracestate");
17546
+ const carrier = traceparent ? tracestate ? { traceparent, tracestate } : { traceparent } : void 0;
17547
+ await withTraceparent(
17548
+ carrier,
17549
+ () => withSpan(
17550
+ `bus.dispatch:${channel}`,
17551
+ () => {
17552
+ const bus = scope ? eventBus2.scope(scope) : eventBus2;
17553
+ const subject = bus.get(channel);
17554
+ subject.next(payload);
17555
+ busLog("EMIT", channel, payload, scope);
17556
+ recordBusEmit(channel, scope);
17557
+ getBusLogger().info("emit", { channel, scope, correlationId: payload.correlationId });
17558
+ },
17559
+ {
17560
+ kind: SpanKind.SERVER,
17561
+ attrs: {
17562
+ "bus.channel": channel,
17563
+ ...scope ? { "bus.scope": scope } : {}
17564
+ }
17565
+ }
17566
+ )
17567
+ );
17887
17568
  return c.json(null, 202);
17888
17569
  });
17889
17570
  return busRouter2;
@@ -17931,22 +17612,22 @@ var securityHeaders = () => {
17931
17612
  init_logger();
17932
17613
  var requestIdMiddleware = async (c, next) => {
17933
17614
  const requestId = randomUUID();
17934
- const logger6 = createChildLogger({ requestId });
17615
+ const logger2 = createChildLogger({ requestId });
17935
17616
  c.set("requestId", requestId);
17936
- c.set("logger", logger6);
17617
+ c.set("logger", logger2);
17937
17618
  c.header("X-Request-ID", requestId);
17938
17619
  await next();
17939
17620
  };
17940
17621
 
17941
17622
  // src/middleware/request-logger.ts
17942
17623
  var requestLoggerMiddleware = async (c, next) => {
17943
- const logger6 = c.get("logger");
17624
+ const logger2 = c.get("logger");
17944
17625
  const startTime = Date.now();
17945
17626
  const method = c.req.method;
17946
17627
  const path2 = c.req.path;
17947
17628
  const query = c.req.query();
17948
17629
  const userAgent = c.req.header("User-Agent") || "unknown";
17949
- logger6.info("Incoming request", {
17630
+ logger2.info("Incoming request", {
17950
17631
  type: "request_incoming",
17951
17632
  method,
17952
17633
  path: path2,
@@ -17956,7 +17637,7 @@ var requestLoggerMiddleware = async (c, next) => {
17956
17637
  await next();
17957
17638
  const duration = Date.now() - startTime;
17958
17639
  const status = c.res.status;
17959
- logger6.info("Outgoing response", {
17640
+ logger2.info("Outgoing response", {
17960
17641
  type: "request_outgoing",
17961
17642
  method,
17962
17643
  path: path2,
@@ -17971,8 +17652,8 @@ var errorLoggerMiddleware = async (c, next) => {
17971
17652
  try {
17972
17653
  await next();
17973
17654
  } catch (error) {
17974
- const logger6 = c.get("logger");
17975
- logger6.error("Unhandled error during request processing", {
17655
+ const logger2 = c.get("logger");
17656
+ logger2.error("Unhandled error during request processing", {
17976
17657
  type: "unhandled_error",
17977
17658
  method: c.req.method,
17978
17659
  path: c.req.path,
@@ -18019,12 +17700,12 @@ if (!config.services.backend.corsOrigin) {
18019
17700
  }
18020
17701
  var backendService = config.services.backend;
18021
17702
  initializeLogger(config.logLevel);
18022
- var logger5 = getLogger();
17703
+ var logger = getLogger();
18023
17704
  {
18024
17705
  const { monitorEventLoopDelay } = await import('perf_hooks');
18025
17706
  const h = monitorEventLoopDelay({ resolution: 20 });
18026
17707
  h.enable();
18027
- const monitorLogger = logger5.child({ component: "event-loop-monitor" });
17708
+ const monitorLogger = logger.child({ component: "event-loop-monitor" });
18028
17709
  setInterval(() => {
18029
17710
  const maxMs = Number((h.max / 1e6).toFixed(1));
18030
17711
  const p99Ms = Number((h.percentile(99) / 1e6).toFixed(1));
@@ -18035,7 +17716,7 @@ var logger5 = getLogger();
18035
17716
  }, 3e4).unref();
18036
17717
  }
18037
17718
  if (databaseUrlConstructed) {
18038
- logger5.info("DATABASE_URL constructed from environment components", {
17719
+ logger.info("DATABASE_URL constructed from environment components", {
18039
17720
  host: process.env.DB_HOST,
18040
17721
  port: process.env.DB_PORT,
18041
17722
  database: process.env.DB_NAME,
@@ -18043,11 +17724,7 @@ if (databaseUrlConstructed) {
18043
17724
  });
18044
17725
  }
18045
17726
  var eventBus = new EventBus();
18046
- var makeMeaning = await startMakeMeaning(new SemiontProject(projectRoot), makeMeaningConfigFrom(config), eventBus, logger5);
18047
- registerJobCommandHandlers(eventBus, makeMeaning.jobQueue);
18048
- registerAnnotationLookupHandlers(eventBus, makeMeaning.knowledgeSystem.kb, makeMeaning.knowledgeSystem.gatherer);
18049
- registerAnnotationAssemblyHandler(eventBus);
18050
- registerBindUpdateBodyHandler(eventBus);
17727
+ var makeMeaning = await startMakeMeaning(new SemiontProject(projectRoot), makeMeaningConfigFrom(config), eventBus, logger);
18051
17728
  var __filename$1 = fileURLToPath(import.meta.url);
18052
17729
  var __dirname$1 = path.dirname(__filename$1);
18053
17730
  var app = new Hono();
@@ -18114,7 +17791,7 @@ app.get("/api/docs", async (c) => {
18114
17791
  return await swaggerHandler(c, async () => {
18115
17792
  });
18116
17793
  } catch (error) {
18117
- logger5.error("Error in /api/docs handler", {
17794
+ logger.error("Error in /api/docs handler", {
18118
17795
  error: error instanceof Error ? error.message : String(error),
18119
17796
  stack: error instanceof Error ? error.stack : void 0
18120
17797
  });
@@ -18131,12 +17808,14 @@ app.all("/api/*", (c) => {
18131
17808
  });
18132
17809
  var port = backendService.port || 4e3;
18133
17810
  if (config.env?.NODE_ENV !== "test") {
17811
+ const { initObservabilityNode } = await import('@semiont/observability/node');
17812
+ initObservabilityNode({ serviceName: "semiont-backend" });
18134
17813
  serve({
18135
17814
  fetch: app.fetch,
18136
17815
  port,
18137
17816
  hostname: "0.0.0.0"
18138
17817
  }, async (info) => {
18139
- logger5.info("Semiont Backend ready", {
17818
+ logger.info("Semiont Backend ready", {
18140
17819
  url: `http://localhost:${info.port}/api`,
18141
17820
  environment: config.env?.NODE_ENV ?? "development"
18142
17821
  });
@@ -18144,18 +17823,18 @@ if (config.env?.NODE_ENV !== "test") {
18144
17823
  const { JWTService: JWTService2 } = await Promise.resolve().then(() => (init_jwt(), jwt_exports));
18145
17824
  JWTService2.initialize(config);
18146
17825
  } catch (error) {
18147
- logger5.error("Failed to initialize JWT Service", {
17826
+ logger.error("Failed to initialize JWT Service", {
18148
17827
  error: error instanceof Error ? error.message : String(error),
18149
17828
  stack: error instanceof Error ? error.stack : void 0
18150
17829
  });
18151
17830
  }
18152
17831
  try {
18153
17832
  const entityTypes = await makeMeaning.knowledgeSystem.kb.graph.getEntityTypes();
18154
- logger5.info("Loaded entity types from graph database", {
17833
+ logger.info("Loaded entity types from graph database", {
18155
17834
  count: entityTypes.length
18156
17835
  });
18157
17836
  } catch (error) {
18158
- logger5.error("Failed to pre-load entity types", {
17837
+ logger.error("Failed to pre-load entity types", {
18159
17838
  error: error instanceof Error ? error.message : String(error),
18160
17839
  stack: error instanceof Error ? error.stack : void 0
18161
17840
  });