@teamscala/service-boot 0.23.314 → 0.23.316
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/package.json
CHANGED
|
@@ -93,16 +93,19 @@ export type AssignTaskInput = v.InferOutput<typeof assignTaskInput>;
|
|
|
93
93
|
* "fn.taskSync is 404" and reached for serving changes, when the row was simply
|
|
94
94
|
* never bound because the body never parsed.
|
|
95
95
|
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
96
|
+
* ROOT-OPTIONAL (`v.optional(v.object(...))`) so it tolerates a caller that sends
|
|
97
|
+
* a DIRECT body or none at all: oRPC extracts `input` from the `{json:{...}}` RPC
|
|
98
|
+
* envelope, so a raw-object or empty POST yields `undefined`, which the optional
|
|
99
|
+
* root ACCEPTS — the handler then falls back to its headers, exactly as it did
|
|
100
|
+
* schema-less (a header-only caller like zerostack is unchanged). An adapter that
|
|
101
|
+
* wants the body path (pi's `parent_id`) POSTs the `{json:{...}}` envelope and
|
|
102
|
+
* `parent_id` is parsed + reaches `adoptAssignmentTask` — the same envelope
|
|
103
|
+
* convention pi ALREADY uses for upsertFromTaskList. A raw-object POST is NOT
|
|
104
|
+
* parsed (oRPC hands the handler `undefined`), which is why pi's bindLaneTask
|
|
105
|
+
* must move to the envelope to deliver `parent_id`. Every field is optional with
|
|
106
|
+
* a header fallback, so the schema ADDS the body path without removing the header.
|
|
104
107
|
*/
|
|
105
|
-
export declare const bindLaneInput: v.ObjectSchema<{
|
|
108
|
+
export declare const bindLaneInput: v.OptionalSchema<v.ObjectSchema<{
|
|
106
109
|
readonly lane: v.OptionalSchema<v.ObjectSchema<{
|
|
107
110
|
readonly pane: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
108
111
|
readonly session: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
@@ -112,7 +115,7 @@ export declare const bindLaneInput: v.ObjectSchema<{
|
|
|
112
115
|
}, undefined>, undefined>;
|
|
113
116
|
readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
114
117
|
readonly parent_id: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
115
|
-
}, undefined>;
|
|
118
|
+
}, undefined>, undefined>;
|
|
116
119
|
/**
|
|
117
120
|
* Resolve the org a dispatched task is created under. Pure: the platform org is
|
|
118
121
|
* INJECTED (resolved by the caller at the handler boundary, where a registry
|
|
@@ -309,8 +309,15 @@ describe("bindLaneInput (body parent_id reaches the adopt path — schema-less g
|
|
|
309
309
|
// A caller transporting everything on headers sends {} (or omits the
|
|
310
310
|
// body); the schema must not reject it, and every field is undefined so the
|
|
311
311
|
// handler's header fallbacks carry the values.
|
|
312
|
-
|
|
313
|
-
|
|
312
|
+
expect(v.safeParse(bindLaneInput, {}).success).toBe(true);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
it("ACCEPTS undefined input — a raw-object POST yields undefined (root-optional)", () => {
|
|
316
|
+
// oRPC extracts input from the {json:{...}} envelope; a raw-object POST
|
|
317
|
+
// (what zerostack/pi send today) yields undefined. The root MUST be optional
|
|
318
|
+
// or those callers 400 instead of falling back to headers. A strict root
|
|
319
|
+
// regressed exactly this (0.23.314), so this assertion locks the tolerance.
|
|
320
|
+
expect(v.safeParse(bindLaneInput, undefined).success).toBe(true);
|
|
314
321
|
});
|
|
315
322
|
|
|
316
323
|
it("treats every field as optional (no caller is forced to populate the body)", () => {
|
|
@@ -105,28 +105,33 @@ export type AssignTaskInput = v.InferOutput<typeof assignTaskInput>;
|
|
|
105
105
|
* "fn.taskSync is 404" and reached for serving changes, when the row was simply
|
|
106
106
|
* never bound because the body never parsed.
|
|
107
107
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
108
|
+
* ROOT-OPTIONAL (`v.optional(v.object(...))`) so it tolerates a caller that sends
|
|
109
|
+
* a DIRECT body or none at all: oRPC extracts `input` from the `{json:{...}}` RPC
|
|
110
|
+
* envelope, so a raw-object or empty POST yields `undefined`, which the optional
|
|
111
|
+
* root ACCEPTS — the handler then falls back to its headers, exactly as it did
|
|
112
|
+
* schema-less (a header-only caller like zerostack is unchanged). An adapter that
|
|
113
|
+
* wants the body path (pi's `parent_id`) POSTs the `{json:{...}}` envelope and
|
|
114
|
+
* `parent_id` is parsed + reaches `adoptAssignmentTask` — the same envelope
|
|
115
|
+
* convention pi ALREADY uses for upsertFromTaskList. A raw-object POST is NOT
|
|
116
|
+
* parsed (oRPC hands the handler `undefined`), which is why pi's bindLaneTask
|
|
117
|
+
* must move to the envelope to deliver `parent_id`. Every field is optional with
|
|
118
|
+
* a header fallback, so the schema ADDS the body path without removing the header.
|
|
116
119
|
*/
|
|
117
|
-
export const bindLaneInput = v.
|
|
118
|
-
|
|
119
|
-
v.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
export const bindLaneInput = v.optional(
|
|
121
|
+
v.object({
|
|
122
|
+
lane: v.optional(
|
|
123
|
+
v.object({
|
|
124
|
+
pane: v.optional(v.string()),
|
|
125
|
+
session: v.optional(v.string()),
|
|
126
|
+
cli_kind: v.optional(v.string()),
|
|
127
|
+
role: v.optional(v.string()),
|
|
128
|
+
organisation_id: v.optional(v.string()),
|
|
129
|
+
}),
|
|
130
|
+
),
|
|
131
|
+
title: v.optional(v.string()),
|
|
132
|
+
parent_id: v.optional(v.string()),
|
|
133
|
+
}),
|
|
134
|
+
);
|
|
130
135
|
|
|
131
136
|
/**
|
|
132
137
|
* Resolve the org a dispatched task is created under. Pure: the platform org is
|
|
@@ -187,7 +187,7 @@ export declare const taskSyncRouter: {
|
|
|
187
187
|
prisma: any;
|
|
188
188
|
user: import("./auth-router.ts").User;
|
|
189
189
|
orgId: string | null | undefined;
|
|
190
|
-
}>, v.ObjectSchema<{
|
|
190
|
+
}>, v.OptionalSchema<v.ObjectSchema<{
|
|
191
191
|
readonly lane: v.OptionalSchema<v.ObjectSchema<{
|
|
192
192
|
readonly pane: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
193
193
|
readonly session: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
@@ -197,7 +197,7 @@ export declare const taskSyncRouter: {
|
|
|
197
197
|
}, undefined>, undefined>;
|
|
198
198
|
readonly title: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
199
199
|
readonly parent_id: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
200
|
-
}, undefined>, import("@orpc/contract").Schema<{
|
|
200
|
+
}, undefined>, undefined>, import("@orpc/contract").Schema<{
|
|
201
201
|
task_id: string;
|
|
202
202
|
created: boolean;
|
|
203
203
|
}, {
|
|
@@ -426,6 +426,11 @@ export const taskSyncRouter = {
|
|
|
426
426
|
const ctx = context as Context;
|
|
427
427
|
const prisma = ctx.prisma as Prisma;
|
|
428
428
|
const log = getAppLogger();
|
|
429
|
+
// DIAG: capture the real exception+stack for the pane-with-run 500
|
|
430
|
+
// (oRPC swallows it to a generic 500; the run-link catch is not firing).
|
|
431
|
+
const __diagPane = (input as { lane?: { pane?: string } })?.lane?.pane ?? ctx.headers?.get("x-lane-pane");
|
|
432
|
+
const __diagSession = (input as { lane?: { session?: string } })?.lane?.session ?? ctx.headers?.get("x-lane-session");
|
|
433
|
+
try {
|
|
429
434
|
// The SessionStart hook sends the pane + the CLI's native session id.
|
|
430
435
|
// SESSION is the match key (kind_data.lane.session) — it is unique per
|
|
431
436
|
// CLI session and re-minted each session, so a fresh session cannot find
|
|
@@ -599,6 +604,14 @@ export const taskSyncRouter = {
|
|
|
599
604
|
});
|
|
600
605
|
}
|
|
601
606
|
return { task_id: taskId, created };
|
|
607
|
+
} catch (__diagErr) {
|
|
608
|
+
log.error("[task-sync] bindLane THREW (diag)", {
|
|
609
|
+
pane: __diagPane, session: __diagSession,
|
|
610
|
+
error: __diagErr instanceof Error ? __diagErr.message : String(__diagErr),
|
|
611
|
+
stack: __diagErr instanceof Error ? __diagErr.stack : undefined,
|
|
612
|
+
});
|
|
613
|
+
throw __diagErr;
|
|
614
|
+
}
|
|
602
615
|
}),
|
|
603
616
|
|
|
604
617
|
/**
|