placementt-core 1.400.1110 → 1.400.1112

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.
@@ -19,7 +19,8 @@ describe("callable registry", () => {
19
19
  });
20
20
  it("names every callable as `<module>-<export>`", () => {
21
21
  for (const name of names) {
22
- expect(name).toMatch(/^[a-zA-Z]+-[a-zA-Z]+$/);
22
+ // Letters first; digits allowed after, for modules like `e2e`.
23
+ expect(name).toMatch(/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z][a-zA-Z0-9]*$/);
23
24
  }
24
25
  });
25
26
  it("gives every callable a request and response zod schema", () => {
@@ -1 +1 @@
1
- {"version":3,"file":"registry.test.js","sourceRoot":"","sources":["../../../src/callables/__tests__/registry.test.ts"],"names":[],"mappings":";;AAAA,6BAAsB;AACtB,0CAAyD;AAEzD;;;;;GAKG;AACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,uBAAY,CAAC,CAAC;IAExC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,yBAAc,CAAC;aAC9C,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAChE,wEAAwE;QACxE,sEAAsE;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAClD,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,uBAAY,CAAC,IAAiC,CAAC,CAAC;YACjE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC;QACxD,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"registry.test.js","sourceRoot":"","sources":["../../../src/callables/__tests__/registry.test.ts"],"names":[],"mappings":";;AAAA,6BAAsB;AACtB,0CAAyD;AAEzD;;;;;GAKG;AACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,uBAAY,CAAC,CAAC;IAExC,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACpD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,yBAAc,CAAC;aAC9C,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAChE,wEAAwE;QACxE,sEAAsE;QACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,+DAA+D;YAC/D,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC;QACxE,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAC9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,uBAAY,CAAC,IAAiC,CAAC,CAAC;YACjE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC;YACnD,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,cAAc,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC;QACxD,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Contracts for the end-to-end and UX-audit harness
4
+ * (`Placementt-Backend/functions/src/e2e.ts`).
5
+ *
6
+ * `redeemSignInLink` is public: the token is the credential. Links are only
7
+ * ever minted by the harness (service account, straight into Firestore) and
8
+ * only ever sign in a reserved `e2e.*@careerthread.co.uk` user, so the UX audit
9
+ * can walk a registered school without anyone typing a password.
10
+ */
11
+ export declare const e2eCallables: {
12
+ "e2e-redeemSignInLink": {
13
+ request: z.ZodObject<{
14
+ /** The raw token from `/e2eSignIn/:token`. Stored only as a SHA-256 hash. */
15
+ token: z.ZodString;
16
+ }, "strip", z.ZodTypeAny, {
17
+ token: string;
18
+ }, {
19
+ token: string;
20
+ }>;
21
+ response: z.ZodObject<{
22
+ code: z.ZodEnum<["ok", "notFound", "expired"]>;
23
+ /** Firebase custom token for the linked e2e user. Only set when code is "ok". */
24
+ authToken: z.ZodOptional<z.ZodString>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ code: "expired" | "ok" | "notFound";
27
+ authToken?: string | undefined;
28
+ }, {
29
+ code: "expired" | "ok" | "notFound";
30
+ authToken?: string | undefined;
31
+ }>;
32
+ };
33
+ };
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.e2eCallables = void 0;
4
+ const zod_1 = require("zod");
5
+ /**
6
+ * Contracts for the end-to-end and UX-audit harness
7
+ * (`Placementt-Backend/functions/src/e2e.ts`).
8
+ *
9
+ * `redeemSignInLink` is public: the token is the credential. Links are only
10
+ * ever minted by the harness (service account, straight into Firestore) and
11
+ * only ever sign in a reserved `e2e.*@careerthread.co.uk` user, so the UX audit
12
+ * can walk a registered school without anyone typing a password.
13
+ */
14
+ exports.e2eCallables = {
15
+ "e2e-redeemSignInLink": {
16
+ request: zod_1.z.object({
17
+ /** The raw token from `/e2eSignIn/:token`. Stored only as a SHA-256 hash. */
18
+ token: zod_1.z.string().min(32).max(128).regex(/^[A-Za-z0-9_-]+$/),
19
+ }),
20
+ response: zod_1.z.object({
21
+ code: zod_1.z.enum(["ok", "notFound", "expired"]),
22
+ /** Firebase custom token for the linked e2e user. Only set when code is "ok". */
23
+ authToken: zod_1.z.string().optional(),
24
+ }),
25
+ },
26
+ };
27
+ //# sourceMappingURL=e2e.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"e2e.js","sourceRoot":"","sources":["../../src/callables/e2e.ts"],"names":[],"mappings":";;;AAAA,6BAAsB;AAGtB;;;;;;;;GAQG;AACU,QAAA,YAAY,GAAG;IACxB,sBAAsB,EAAE;QACpB,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC;YACd,6EAA6E;YAC7E,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;SAC/D,CAAC;QACF,QAAQ,EAAE,OAAC,CAAC,MAAM,CAAC;YACf,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;YAC3C,iFAAiF;YACjF,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SACnC,CAAC;KACL;CACoB,CAAC"}
@@ -9,3 +9,4 @@ export * from "./he";
9
9
  export * from "./studentLaunches";
10
10
  export * from "./billing";
11
11
  export * from "./hubImpactReport";
12
+ export * from "./e2e";
@@ -25,4 +25,5 @@ __exportStar(require("./he"), exports);
25
25
  __exportStar(require("./studentLaunches"), exports);
26
26
  __exportStar(require("./billing"), exports);
27
27
  __exportStar(require("./hubImpactReport"), exports);
28
+ __exportStar(require("./e2e"), exports);
28
29
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/callables/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,6CAA2B;AAC3B,uDAAqC;AACrC,8CAA4B;AAC5B,2CAAyB;AACzB,6CAA2B;AAC3B,oDAAkC;AAClC,uCAAqB;AACrB,oDAAkC;AAClC,4CAA0B;AAC1B,oDAAkC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/callables/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,0CAAwB;AACxB,6CAA2B;AAC3B,uDAAqC;AACrC,8CAA4B;AAC5B,2CAAyB;AACzB,6CAA2B;AAC3B,oDAAkC;AAClC,uCAAqB;AACrB,oDAAkC;AAClC,4CAA0B;AAC1B,oDAAkC;AAClC,wCAAsB"}
@@ -11,6 +11,25 @@ import { z } from "zod";
11
11
  * equals the sum of the group key counts.
12
12
  */
13
13
  export declare const allCallables: {
14
+ "e2e-redeemSignInLink": {
15
+ request: z.ZodObject<{
16
+ token: z.ZodString;
17
+ }, "strip", z.ZodTypeAny, {
18
+ token: string;
19
+ }, {
20
+ token: string;
21
+ }>;
22
+ response: z.ZodObject<{
23
+ code: z.ZodEnum<["ok", "notFound", "expired"]>;
24
+ authToken: z.ZodOptional<z.ZodString>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ code: "expired" | "ok" | "notFound";
27
+ authToken?: string | undefined;
28
+ }, {
29
+ code: "expired" | "ok" | "notFound";
30
+ authToken?: string | undefined;
31
+ }>;
32
+ };
14
33
  "hubImpactReport-createHubImpactReport": {
15
34
  request: z.ZodObject<{
16
35
  oId: z.ZodOptional<z.ZodString>;
@@ -2515,4 +2534,25 @@ export declare const callableGroups: {
2515
2534
  response: z.ZodString;
2516
2535
  };
2517
2536
  };
2537
+ e2eCallables: {
2538
+ "e2e-redeemSignInLink": {
2539
+ request: z.ZodObject<{
2540
+ token: z.ZodString;
2541
+ }, "strip", z.ZodTypeAny, {
2542
+ token: string;
2543
+ }, {
2544
+ token: string;
2545
+ }>;
2546
+ response: z.ZodObject<{
2547
+ code: z.ZodEnum<["ok", "notFound", "expired"]>;
2548
+ authToken: z.ZodOptional<z.ZodString>;
2549
+ }, "strip", z.ZodTypeAny, {
2550
+ code: "expired" | "ok" | "notFound";
2551
+ authToken?: string | undefined;
2552
+ }, {
2553
+ code: "expired" | "ok" | "notFound";
2554
+ authToken?: string | undefined;
2555
+ }>;
2556
+ };
2557
+ };
2518
2558
  };
@@ -13,6 +13,7 @@ const studentLaunches_1 = require("./studentLaunches");
13
13
  const billing_1 = require("./billing");
14
14
  const jobRoles_1 = require("./jobRoles");
15
15
  const hubImpactReport_1 = require("./hubImpactReport");
16
+ const e2e_1 = require("./e2e");
16
17
  /**
17
18
  * The single source of truth for every typed callable. Add a feature group's
18
19
  * spread here and its callables are automatically covered by:
@@ -37,7 +38,8 @@ exports.allCallables = {
37
38
  ...billing_1.billingCallables,
38
39
  ...jobRoles_1.jobRolesCallables,
39
40
  ...hubImpactReport_1.hubImpactReportCallables,
41
+ ...e2e_1.e2eCallables,
40
42
  };
41
43
  /** The per-group maps, exported so tests can assert no key collisions. */
42
- exports.callableGroups = { destinationsConfigCallables: destinationsConfig_1.destinationsConfigCallables, placementCallables: placement_1.placementCallables, eventsCallables: events_1.eventsCallables, surveyCallables: surveys_1.surveyCallables, checksCallables: checks_1.checksCallables, benchmarksCallables: benchmarks_1.benchmarksCallables, apprenticeshipsCallables: apprenticeships_1.apprenticeshipsCallables, heCallables: he_1.heCallables, studentLaunchCallables: studentLaunches_1.studentLaunchCallables, billingCallables: billing_1.billingCallables, jobRolesCallables: jobRoles_1.jobRolesCallables, hubImpactReportCallables: hubImpactReport_1.hubImpactReportCallables };
44
+ exports.callableGroups = { destinationsConfigCallables: destinationsConfig_1.destinationsConfigCallables, placementCallables: placement_1.placementCallables, eventsCallables: events_1.eventsCallables, surveyCallables: surveys_1.surveyCallables, checksCallables: checks_1.checksCallables, benchmarksCallables: benchmarks_1.benchmarksCallables, apprenticeshipsCallables: apprenticeships_1.apprenticeshipsCallables, heCallables: he_1.heCallables, studentLaunchCallables: studentLaunches_1.studentLaunchCallables, billingCallables: billing_1.billingCallables, jobRolesCallables: jobRoles_1.jobRolesCallables, hubImpactReportCallables: hubImpactReport_1.hubImpactReportCallables, e2eCallables: e2e_1.e2eCallables };
43
45
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/callables/registry.ts"],"names":[],"mappings":";;;AAEA,6DAAiE;AACjE,2CAA+C;AAC/C,qCAAyC;AACzC,uCAA0C;AAC1C,qCAAyC;AACzC,6CAAiD;AACjD,uDAA2D;AAC3D,6BAAiC;AACjC,uDAAyD;AACzD,uCAA2C;AAC3C,yCAA6C;AAC7C,uDAA2D;AAE3D;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAG;IACxB,GAAG,gDAA2B;IAC9B,GAAG,8BAAkB;IACrB,GAAG,wBAAe;IAClB,GAAG,yBAAe;IAClB,GAAG,wBAAe;IAClB,GAAG,gCAAmB;IACtB,GAAG,0CAAwB;IAC3B,GAAG,gBAAW;IACd,GAAG,wCAAsB;IACzB,GAAG,0BAAgB;IACnB,GAAG,4BAAiB;IACpB,GAAG,0CAAwB;CACN,CAAC;AAiB1B,0EAA0E;AAC7D,QAAA,cAAc,GAAG,EAAC,2BAA2B,EAA3B,gDAA2B,EAAE,kBAAkB,EAAlB,8BAAkB,EAAE,eAAe,EAAf,wBAAe,EAAE,eAAe,EAAf,yBAAe,EAAE,eAAe,EAAf,wBAAe,EAAE,mBAAmB,EAAnB,gCAAmB,EAAE,wBAAwB,EAAxB,0CAAwB,EAAE,WAAW,EAAX,gBAAW,EAAE,sBAAsB,EAAtB,wCAAsB,EAAE,gBAAgB,EAAhB,0BAAgB,EAAE,iBAAiB,EAAjB,4BAAiB,EAAE,wBAAwB,EAAxB,0CAAwB,EAAC,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/callables/registry.ts"],"names":[],"mappings":";;;AAEA,6DAAiE;AACjE,2CAA+C;AAC/C,qCAAyC;AACzC,uCAA0C;AAC1C,qCAAyC;AACzC,6CAAiD;AACjD,uDAA2D;AAC3D,6BAAiC;AACjC,uDAAyD;AACzD,uCAA2C;AAC3C,yCAA6C;AAC7C,uDAA2D;AAC3D,+BAAmC;AAEnC;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAG;IACxB,GAAG,gDAA2B;IAC9B,GAAG,8BAAkB;IACrB,GAAG,wBAAe;IAClB,GAAG,yBAAe;IAClB,GAAG,wBAAe;IAClB,GAAG,gCAAmB;IACtB,GAAG,0CAAwB;IAC3B,GAAG,gBAAW;IACd,GAAG,wCAAsB;IACzB,GAAG,0BAAgB;IACnB,GAAG,4BAAiB;IACpB,GAAG,0CAAwB;IAC3B,GAAG,kBAAY;CACM,CAAC;AAiB1B,0EAA0E;AAC7D,QAAA,cAAc,GAAG,EAAC,2BAA2B,EAA3B,gDAA2B,EAAE,kBAAkB,EAAlB,8BAAkB,EAAE,eAAe,EAAf,wBAAe,EAAE,eAAe,EAAf,yBAAe,EAAE,eAAe,EAAf,wBAAe,EAAE,mBAAmB,EAAnB,gCAAmB,EAAE,wBAAwB,EAAxB,0CAAwB,EAAE,WAAW,EAAX,gBAAW,EAAE,sBAAsB,EAAtB,wCAAsB,EAAE,gBAAgB,EAAhB,0BAAgB,EAAE,iBAAiB,EAAjB,4BAAiB,EAAE,wBAAwB,EAAxB,0CAAwB,EAAE,YAAY,EAAZ,kBAAY,EAAC,CAAC"}
@@ -1045,6 +1045,8 @@ export type EmployerField = {
1045
1045
  multiple?: boolean;
1046
1046
  required?: boolean;
1047
1047
  };
1048
+ /** The areas of the staff platform that each own part of the careers year. */
1049
+ export type CareersSetupArea = "development" | "destinations";
1048
1050
  export type InstituteData = {
1049
1051
  students: number;
1050
1052
  staff: number;
@@ -1163,7 +1165,14 @@ export type InstituteData = {
1163
1165
  };
1164
1166
  destinationsConfig?: DestinationsConfig;
1165
1167
  guidanceConfig?: GuidanceConfig;
1168
+ /** "Set up later" from the careers calendar's whole-year flow. Holds until the
1169
+ * next 1 September, so the year is offered again when it actually changes. */
1166
1170
  careersYearSetupDeferredAt?: string;
1171
+ /** The same, said from inside one area's own flow. Development's "later" is no
1172
+ * answer about Destinations, so each area keeps its own. */
1173
+ careersAreaSetupDeferredAt?: {
1174
+ [area in CareersSetupArea]?: string;
1175
+ };
1167
1176
  leaverDestinations?: {
1168
1177
  [id: string]: LeaverDestination;
1169
1178
  };
@@ -1 +1 @@
1
- {"version":3,"file":"typeDefinitions.js","sourceRoot":"","sources":["../src/typeDefinitions.ts"],"names":[],"mappings":";;;AAoiIA,sDASC;AAeD,oDAKC;AAaD,0CAEC;AA/nED;;;;;kFAKkF;AACrE,QAAA,qBAAqB,GAAG,SAAS,CAAC;AAClC,QAAA,iBAAiB,GAAG,OAAO,CAAC;AA2iEzC;yEACyE;AAC5D,QAAA,0BAA0B,GAA2C;IAC9E,gBAAgB,EAAE,2BAA2B;IAC7C,mBAAmB,EAAE,sBAAsB;IAC3C,cAAc,EAAE,iBAAiB;IACjC,kBAAkB,EAAE,qBAAqB;IACzC,UAAU,EAAE,oCAAoC;IAChD,aAAa,EAAE,yBAAyB;IACxC,aAAa,EAAE,wBAAwB;IACvC,KAAK,EAAE,OAAO;CACjB,CAAC;AAEW,QAAA,0BAA0B,GAA+C;IAClF,QAAQ,EAAE,WAAW;IACrB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,OAAO;CACjB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,SAAgB,qBAAqB,CAAC,SAAsC;IACxE,QAAQ,SAAS,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC;QAC5B,KAAK,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC;QAC7B,KAAK,WAAW,CAAC;QACjB,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,OAAO,CAAC,CAAC,OAAO,UAAU,CAAC;IAC3B,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,oBAAoB,CAChC,IAAwC,EACxC,MAA6C;IAE7C,OAAO,IAAI,EAAE,WAAW,IAAI,MAAM,EAAE,YAAY,IAAI,KAAK,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,eAAe,CAAC,KAA6D;IACzF,OAAO,GAAG,KAAK,CAAC,cAAc,IAAI,EAAE,IAAI,KAAK,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AAC/E,CAAC"}
1
+ {"version":3,"file":"typeDefinitions.js","sourceRoot":"","sources":["../src/typeDefinitions.ts"],"names":[],"mappings":";;;AA4iIA,sDASC;AAeD,oDAKC;AAaD,0CAEC;AA/nED;;;;;kFAKkF;AACrE,QAAA,qBAAqB,GAAG,SAAS,CAAC;AAClC,QAAA,iBAAiB,GAAG,OAAO,CAAC;AA2iEzC;yEACyE;AAC5D,QAAA,0BAA0B,GAA2C;IAC9E,gBAAgB,EAAE,2BAA2B;IAC7C,mBAAmB,EAAE,sBAAsB;IAC3C,cAAc,EAAE,iBAAiB;IACjC,kBAAkB,EAAE,qBAAqB;IACzC,UAAU,EAAE,oCAAoC;IAChD,aAAa,EAAE,yBAAyB;IACxC,aAAa,EAAE,wBAAwB;IACvC,KAAK,EAAE,OAAO;CACjB,CAAC;AAEW,QAAA,0BAA0B,GAA+C;IAClF,QAAQ,EAAE,WAAW;IACrB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,OAAO;CACjB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,SAAgB,qBAAqB,CAAC,SAAsC;IACxE,QAAQ,SAAS,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,CAAC,OAAO,OAAO,CAAC;QAC5B,KAAK,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC;QAC7B,KAAK,WAAW,CAAC;QACjB,KAAK,OAAO,CAAC;QACb,KAAK,OAAO,CAAC;QACb,OAAO,CAAC,CAAC,OAAO,UAAU,CAAC;IAC3B,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAgB,oBAAoB,CAChC,IAAwC,EACxC,MAA6C;IAE7C,OAAO,IAAI,EAAE,WAAW,IAAI,MAAM,EAAE,YAAY,IAAI,KAAK,CAAC;AAC9D,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,eAAe,CAAC,KAA6D;IACzF,OAAO,GAAG,KAAK,CAAC,cAAc,IAAI,EAAE,IAAI,KAAK,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;AAC/E,CAAC"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "private": false,
3
3
  "name": "placementt-core",
4
4
  "author": "Placementt",
5
- "version": "1.400.1110",
5
+ "version": "1.400.1112",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
8
8
  "scripts": {
@@ -20,7 +20,8 @@ describe("callable registry", () => {
20
20
 
21
21
  it("names every callable as `<module>-<export>`", () => {
22
22
  for (const name of names) {
23
- expect(name).toMatch(/^[a-zA-Z]+-[a-zA-Z]+$/);
23
+ // Letters first; digits allowed after, for modules like `e2e`.
24
+ expect(name).toMatch(/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z][a-zA-Z0-9]*$/);
24
25
  }
25
26
  });
26
27
 
@@ -0,0 +1,25 @@
1
+ import {z} from "zod";
2
+ import {CallableGroup} from "./types";
3
+
4
+ /**
5
+ * Contracts for the end-to-end and UX-audit harness
6
+ * (`Placementt-Backend/functions/src/e2e.ts`).
7
+ *
8
+ * `redeemSignInLink` is public: the token is the credential. Links are only
9
+ * ever minted by the harness (service account, straight into Firestore) and
10
+ * only ever sign in a reserved `e2e.*@careerthread.co.uk` user, so the UX audit
11
+ * can walk a registered school without anyone typing a password.
12
+ */
13
+ export const e2eCallables = {
14
+ "e2e-redeemSignInLink": {
15
+ request: z.object({
16
+ /** The raw token from `/e2eSignIn/:token`. Stored only as a SHA-256 hash. */
17
+ token: z.string().min(32).max(128).regex(/^[A-Za-z0-9_-]+$/),
18
+ }),
19
+ response: z.object({
20
+ code: z.enum(["ok", "notFound", "expired"]),
21
+ /** Firebase custom token for the linked e2e user. Only set when code is "ok". */
22
+ authToken: z.string().optional(),
23
+ }),
24
+ },
25
+ } satisfies CallableGroup;
@@ -9,3 +9,4 @@ export * from "./he";
9
9
  export * from "./studentLaunches";
10
10
  export * from "./billing";
11
11
  export * from "./hubImpactReport";
12
+ export * from "./e2e";
@@ -12,6 +12,7 @@ import {studentLaunchCallables} from "./studentLaunches";
12
12
  import {billingCallables} from "./billing";
13
13
  import {jobRolesCallables} from "./jobRoles";
14
14
  import {hubImpactReportCallables} from "./hubImpactReport";
15
+ import {e2eCallables} from "./e2e";
15
16
 
16
17
  /**
17
18
  * The single source of truth for every typed callable. Add a feature group's
@@ -37,6 +38,7 @@ export const allCallables = {
37
38
  ...billingCallables,
38
39
  ...jobRolesCallables,
39
40
  ...hubImpactReportCallables,
41
+ ...e2eCallables,
40
42
  } satisfies CallableGroup;
41
43
 
42
44
  /** Every registered callable name. */
@@ -55,4 +57,4 @@ export type CallableContracts = {
55
57
  };
56
58
 
57
59
  /** The per-group maps, exported so tests can assert no key collisions. */
58
- export const callableGroups = {destinationsConfigCallables, placementCallables, eventsCallables, surveyCallables, checksCallables, benchmarksCallables, apprenticeshipsCallables, heCallables, studentLaunchCallables, billingCallables, jobRolesCallables, hubImpactReportCallables};
60
+ export const callableGroups = {destinationsConfigCallables, placementCallables, eventsCallables, surveyCallables, checksCallables, benchmarksCallables, apprenticeshipsCallables, heCallables, studentLaunchCallables, billingCallables, jobRolesCallables, hubImpactReportCallables, e2eCallables};
@@ -1086,6 +1086,9 @@ export type EmployerField = {
1086
1086
  required?: boolean,
1087
1087
  }
1088
1088
 
1089
+ /** The areas of the staff platform that each own part of the careers year. */
1090
+ export type CareersSetupArea = "development"|"destinations";
1091
+
1089
1092
  export type InstituteData = {
1090
1093
  students: number,
1091
1094
  staff: number,
@@ -1193,7 +1196,12 @@ export type InstituteData = {
1193
1196
  },
1194
1197
  destinationsConfig?: DestinationsConfig,
1195
1198
  guidanceConfig?: GuidanceConfig,
1199
+ /** "Set up later" from the careers calendar's whole-year flow. Holds until the
1200
+ * next 1 September, so the year is offered again when it actually changes. */
1196
1201
  careersYearSetupDeferredAt?: string,
1202
+ /** The same, said from inside one area's own flow. Development's "later" is no
1203
+ * answer about Destinations, so each area keeps its own. */
1204
+ careersAreaSetupDeferredAt?: {[area in CareersSetupArea]?: string},
1197
1205
  leaverDestinations?: {[id: string]: LeaverDestination},
1198
1206
  trustPolicies?: {[feature in TrustPolicyFeature]?: TrustPolicy},
1199
1207
  studentTasks?: StudentTaskConfigMap,