@microck/canonfig 2.0.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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +263 -0
  3. package/dist/agent/agent-resolution.errors.js +42 -0
  4. package/dist/agent/agent-resolution.layer.js +204 -0
  5. package/dist/agent/agent-resolution.service.js +2259 -0
  6. package/dist/agent/agent-resolution.types.js +1 -0
  7. package/dist/agent/controlled-executor.js +704 -0
  8. package/dist/agent/harness-adapters.js +85 -0
  9. package/dist/cli/cli.js +618 -0
  10. package/dist/cli/exit-codes.js +28 -0
  11. package/dist/cli/follower-commands.js +3 -0
  12. package/dist/cli/render.js +56 -0
  13. package/dist/cli/source-commands.js +5 -0
  14. package/dist/domain/brand.js +29 -0
  15. package/dist/domain/identity.js +31 -0
  16. package/dist/domain/npm-package-spec.js +186 -0
  17. package/dist/domain/profile.js +950 -0
  18. package/dist/domain/recipe-versions.js +297 -0
  19. package/dist/domain/resource.js +259 -0
  20. package/dist/domain/synchronization.js +346 -0
  21. package/dist/enrollment/enrollment.errors.js +43 -0
  22. package/dist/enrollment/enrollment.layer.js +724 -0
  23. package/dist/enrollment/enrollment.service.js +3 -0
  24. package/dist/enrollment/enrollment.types.js +59 -0
  25. package/dist/enrollment/follower-client.js +585 -0
  26. package/dist/enrollment/source-server.js +313 -0
  27. package/dist/machine/linux.layer.js +1183 -0
  28. package/dist/machine/machine-state.errors.js +52 -0
  29. package/dist/machine/machine-state.service.js +3 -0
  30. package/dist/machine/machine-state.types.js +1 -0
  31. package/dist/machine/macos.layer.js +470 -0
  32. package/dist/machine/windows.layer.js +879 -0
  33. package/dist/profile/discovery.js +740 -0
  34. package/dist/profile/profile-catalog.errors.js +50 -0
  35. package/dist/profile/profile-catalog.layer.js +20 -0
  36. package/dist/profile/profile-catalog.service.js +7 -0
  37. package/dist/profile/profile-codec.js +153 -0
  38. package/dist/profile/publication.js +298 -0
  39. package/dist/profile/tool-catalog.js +384 -0
  40. package/dist/runtime/doctor.js +306 -0
  41. package/dist/runtime/layers.js +706 -0
  42. package/dist/runtime/main.js +38 -0
  43. package/dist/schedule/linux-schedule.js +24 -0
  44. package/dist/schedule/macos-schedule.js +25 -0
  45. package/dist/schedule/schedule-manager.errors.js +17 -0
  46. package/dist/schedule/schedule-manager.layer.js +205 -0
  47. package/dist/schedule/schedule-manager.service.js +3 -0
  48. package/dist/schedule/schedule-manager.types.js +114 -0
  49. package/dist/schedule/windows-schedule.js +25 -0
  50. package/dist/state/state-repository.errors.js +55 -0
  51. package/dist/state/state-repository.layer.js +1507 -0
  52. package/dist/state/state-repository.service.js +3 -0
  53. package/dist/state/state-repository.types.js +1 -0
  54. package/dist/state/state-schema.js +298 -0
  55. package/dist/synchronization/config-codec.js +97 -0
  56. package/dist/synchronization/executor.js +700 -0
  57. package/dist/synchronization/follower-orchestration.js +939 -0
  58. package/dist/synchronization/follower-sync-config.js +81 -0
  59. package/dist/synchronization/npm-artifact.js +670 -0
  60. package/dist/synchronization/planner.js +378 -0
  61. package/dist/synchronization/recovery.js +397 -0
  62. package/dist/synchronization/resource-executors.js +1198 -0
  63. package/dist/synchronization/resource-plans.js +645 -0
  64. package/dist/synchronization/synchronization.errors.js +102 -0
  65. package/dist/synchronization/synchronization.layer.js +97 -0
  66. package/dist/synchronization/synchronization.service.js +11 -0
  67. package/dist/synchronization/synchronization.types.js +1 -0
  68. package/package.json +66 -0
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ import { NodeRuntime } from "@effect/platform-node";
3
+ import { Effect } from "effect";
4
+ import { evaluateCli, runCli } from "../cli/cli.js";
5
+ const warningListeners = process.listeners("warning");
6
+ process.removeAllListeners("warning");
7
+ process.on("warning", (warning) => {
8
+ if (warning.name === "ExperimentalWarning"
9
+ && warning.message === "SQLite is an experimental feature and might change at any time")
10
+ return;
11
+ for (const listener of warningListeners)
12
+ listener.call(process, warning);
13
+ });
14
+ const nodeCliIo = {
15
+ writeStdout: (text) => process.stdout.write(text),
16
+ writeStderr: (text) => process.stderr.write(text),
17
+ setExitCode: (exitCode) => {
18
+ process.exitCode = exitCode;
19
+ },
20
+ };
21
+ const arguments_ = process.argv.slice(2);
22
+ const outcome = evaluateCli(arguments_);
23
+ if (outcome._tag === "Command") {
24
+ NodeRuntime.runMain(Effect.promise(() => import("./layers.js")).pipe(Effect.flatMap(({ runtimeLayer }) => runCli(arguments_, nodeCliIo).pipe(Effect.andThen(outcome.command._tag === "SourceServe"
25
+ ? Effect.never
26
+ : Effect.void), Effect.provide(runtimeLayer())))));
27
+ }
28
+ else {
29
+ NodeRuntime.runMain(Effect.sync(() => {
30
+ if (outcome._tag === "Help" || outcome._tag === "Version") {
31
+ nodeCliIo.writeStdout(`${outcome.text}\n`);
32
+ }
33
+ else {
34
+ nodeCliIo.writeStderr(`${outcome.message}\n`);
35
+ }
36
+ nodeCliIo.setExitCode(outcome.exitCode);
37
+ }));
38
+ }
@@ -0,0 +1,24 @@
1
+ import { normalizeSyncSchedule, } from "./schedule-manager.types.js";
2
+ export const linuxCalendar = (input) => {
3
+ const schedule = normalizeSyncSchedule(input);
4
+ if (schedule.kind === "daily") {
5
+ return {
6
+ kind: "daily",
7
+ localTime: schedule.localTime,
8
+ timezone: schedule.timezone,
9
+ };
10
+ }
11
+ if (schedule.kind === "weekly") {
12
+ return {
13
+ kind: "weekly",
14
+ weekdays: schedule.weekdays,
15
+ localTime: schedule.localTime,
16
+ timezone: schedule.timezone,
17
+ };
18
+ }
19
+ return {
20
+ kind: "systemd-on-calendar",
21
+ expression: schedule.expression,
22
+ timezone: schedule.timezone,
23
+ };
24
+ };
@@ -0,0 +1,25 @@
1
+ import { Effect } from "effect";
2
+ import { ScheduleHumanActionRequiredError } from "./schedule-manager.errors.js";
3
+ import { normalizeSyncSchedule, } from "./schedule-manager.types.js";
4
+ export const macosCalendar = (schedule) => {
5
+ schedule = normalizeSyncSchedule(schedule);
6
+ if (schedule.kind === "custom") {
7
+ return Effect.fail(new ScheduleHumanActionRequiredError({
8
+ action: "use a daily or weekly schedule on macOS",
9
+ recovery: "launchd does not support the requested custom calendar expression. Choose a daily or weekly schedule, then retry.",
10
+ }));
11
+ }
12
+ if (schedule.timezone !== undefined) {
13
+ return Effect.fail(new ScheduleHumanActionRequiredError({
14
+ action: "use the macOS follower timezone for scheduled sync",
15
+ recovery: "launchd calendar intervals follow the macOS user timezone and cannot bind a named timezone. Remove the explicit timezone or change the follower timezone.",
16
+ }));
17
+ }
18
+ return Effect.succeed(schedule.kind === "daily"
19
+ ? { kind: "daily", localTime: schedule.localTime }
20
+ : {
21
+ kind: "weekly",
22
+ weekdays: schedule.weekdays,
23
+ localTime: schedule.localTime,
24
+ });
25
+ };
@@ -0,0 +1,17 @@
1
+ import { Schema } from "effect";
2
+ export class InvalidScheduleError extends Schema.TaggedError()("InvalidScheduleError", {
3
+ field: Schema.String,
4
+ message: Schema.String,
5
+ }) {
6
+ }
7
+ export class ScheduleHumanActionRequiredError extends Schema.TaggedError()("ScheduleHumanActionRequiredError", {
8
+ action: Schema.String,
9
+ recovery: Schema.String,
10
+ }) {
11
+ }
12
+ export class ScheduleVerificationError extends Schema.TaggedError()("ScheduleVerificationError", {
13
+ operation: Schema.String,
14
+ state: Schema.String,
15
+ message: Schema.String,
16
+ }) {
17
+ }
@@ -0,0 +1,205 @@
1
+ import { Effect, Layer } from "effect";
2
+ import { MachineState } from "../machine/machine-state.service.js";
3
+ import { linuxCalendar } from "./linux-schedule.js";
4
+ import { macosCalendar } from "./macos-schedule.js";
5
+ import { InvalidScheduleError, ScheduleVerificationError, } from "./schedule-manager.errors.js";
6
+ import { ScheduleManager } from "./schedule-manager.service.js";
7
+ import { defaultSyncSchedule, normalizeSyncSchedule, } from "./schedule-manager.types.js";
8
+ import { windowsCalendar } from "./windows-schedule.js";
9
+ const syncArguments = ["sync", "--apply", "--no-input"];
10
+ const validLocalTime = /^([01]\d|2[0-3]):[0-5]\d$/u;
11
+ const validateSchedule = (schedule) => {
12
+ schedule = normalizeSyncSchedule(schedule);
13
+ if (schedule.kind === "custom") {
14
+ if (schedule.expression.trim() !== schedule.expression
15
+ || schedule.expression.length === 0
16
+ || /[\n\r\0]/u.test(schedule.expression)) {
17
+ return Effect.fail(new InvalidScheduleError({
18
+ field: "expression",
19
+ message: "custom calendar expression must be non-empty and single-line",
20
+ }));
21
+ }
22
+ if (schedule.timezone === undefined)
23
+ return Effect.succeed(schedule);
24
+ if (schedule.timezone.trim() !== schedule.timezone
25
+ || schedule.timezone.length === 0
26
+ || /[\n\r\0]/u.test(schedule.timezone)) {
27
+ return Effect.fail(new InvalidScheduleError({
28
+ field: "timezone",
29
+ message: "timezone must be a non-empty IANA timezone name",
30
+ }));
31
+ }
32
+ try {
33
+ new Intl.DateTimeFormat("en-US", { timeZone: schedule.timezone }).format();
34
+ }
35
+ catch {
36
+ return Effect.fail(new InvalidScheduleError({
37
+ field: "timezone",
38
+ message: `unsupported IANA timezone: ${schedule.timezone}`,
39
+ }));
40
+ }
41
+ return Effect.succeed(schedule);
42
+ }
43
+ if (!validLocalTime.test(schedule.localTime)) {
44
+ return Effect.fail(new InvalidScheduleError({
45
+ field: "localTime",
46
+ message: "local time must use 24-hour HH:mm format",
47
+ }));
48
+ }
49
+ if (schedule.kind === "weekly" && schedule.weekdays.length === 0) {
50
+ return Effect.fail(new InvalidScheduleError({
51
+ field: "weekdays",
52
+ message: "weekly schedule must declare at least one weekday",
53
+ }));
54
+ }
55
+ if (schedule.timezone === undefined)
56
+ return Effect.succeed(schedule);
57
+ if (schedule.timezone.trim() !== schedule.timezone
58
+ || schedule.timezone.length === 0
59
+ || /[\n\r\0]/u.test(schedule.timezone)) {
60
+ return Effect.fail(new InvalidScheduleError({
61
+ field: "timezone",
62
+ message: "timezone must be a non-empty IANA timezone name",
63
+ }));
64
+ }
65
+ try {
66
+ new Intl.DateTimeFormat("en-US", { timeZone: schedule.timezone }).format();
67
+ }
68
+ catch {
69
+ return Effect.fail(new InvalidScheduleError({
70
+ field: "timezone",
71
+ message: `unsupported IANA timezone: ${schedule.timezone}`,
72
+ }));
73
+ }
74
+ return Effect.succeed(schedule);
75
+ };
76
+ const calendarFor = (platform, schedule) => {
77
+ switch (platform) {
78
+ case "linux":
79
+ return Effect.succeed(linuxCalendar(schedule));
80
+ case "macos":
81
+ return macosCalendar(schedule);
82
+ case "windows":
83
+ return windowsCalendar(schedule);
84
+ }
85
+ };
86
+ const stateOf = (installed, enabled, matches) => {
87
+ if (!installed)
88
+ return "not-installed";
89
+ if (!matches)
90
+ return "drifted";
91
+ return enabled ? "current" : "disabled";
92
+ };
93
+ const snapshotsEqual = (left, right) => JSON.stringify(left) === JSON.stringify(right);
94
+ export const scheduleManagerLayer = Layer.effect(ScheduleManager, Effect.gen(function* () {
95
+ const machine = yield* MachineState;
96
+ const definition = Effect.fn("ScheduleManager.definition")(function* (input = {}) {
97
+ const schedule = yield* validateSchedule(input.schedule ?? defaultSyncSchedule);
98
+ const executable = input.executable === undefined
99
+ ? (yield* machine.findExecutable({ name: "canonfig" })).path
100
+ : yield* machine.normalizePath({ path: input.executable });
101
+ const calendar = yield* calendarFor(executable.platform, schedule);
102
+ const rendered = yield* machine.renderSchedulerJob({
103
+ name: "canonfig-sync",
104
+ description: "Canonfig follower synchronization",
105
+ executable,
106
+ arguments: syncArguments,
107
+ calendar,
108
+ });
109
+ return { schedule, definition: rendered };
110
+ });
111
+ const inspect = Effect.fn("ScheduleManager.inspect")(function* (input = {}) {
112
+ const desired = yield* definition(input);
113
+ const inspection = yield* machine.inspectSchedulerJob(desired.definition);
114
+ return {
115
+ state: stateOf(inspection.installed, inspection.enabled, inspection.matches),
116
+ platform: desired.definition.platform,
117
+ schedule: desired.schedule,
118
+ definition: desired.definition,
119
+ };
120
+ });
121
+ const snapshot = Effect.fn("ScheduleManager.snapshot")(function* (input = {}) {
122
+ const desired = yield* definition(input);
123
+ return yield* machine.snapshotSchedulerJob(desired.definition);
124
+ });
125
+ const restore = Effect.fn("ScheduleManager.restore")(function* (input, prior) {
126
+ const desired = yield* definition(input ?? {});
127
+ if (prior.platform !== desired.definition.platform
128
+ || prior.mechanism !== desired.definition.mechanism
129
+ || prior.serviceName !== desired.definition.serviceName) {
130
+ return yield* new ScheduleVerificationError({
131
+ operation: "restore",
132
+ state: "invalid-snapshot",
133
+ message: "native scheduler snapshot does not belong to this schedule",
134
+ });
135
+ }
136
+ yield* machine.restoreSchedulerJob(desired.definition, prior);
137
+ const after = yield* machine.snapshotSchedulerJob(desired.definition);
138
+ if (!snapshotsEqual(after, prior)) {
139
+ return yield* new ScheduleVerificationError({
140
+ operation: "restore",
141
+ state: after.state,
142
+ message: "native scheduler did not restore its exact prior state",
143
+ });
144
+ }
145
+ });
146
+ const upsert = Effect.fn("ScheduleManager.upsert")(function* (input = {}) {
147
+ const desired = yield* definition(input);
148
+ const before = yield* machine.inspectSchedulerJob(desired.definition);
149
+ if (before.installed && before.enabled && before.matches) {
150
+ return {
151
+ change: "unchanged",
152
+ status: {
153
+ state: "current",
154
+ platform: desired.definition.platform,
155
+ schedule: desired.schedule,
156
+ definition: desired.definition,
157
+ },
158
+ };
159
+ }
160
+ yield* machine.installSchedulerJob(desired.definition);
161
+ const after = yield* machine.inspectSchedulerJob(desired.definition);
162
+ const afterState = stateOf(after.installed, after.enabled, after.matches);
163
+ if (afterState !== "current") {
164
+ return yield* new ScheduleVerificationError({
165
+ operation: before.installed ? "update" : "install",
166
+ state: afterState,
167
+ message: "native scheduler did not converge to the requested definition",
168
+ });
169
+ }
170
+ return {
171
+ change: before.installed ? "updated" : "installed",
172
+ status: {
173
+ state: afterState,
174
+ platform: desired.definition.platform,
175
+ schedule: desired.schedule,
176
+ definition: desired.definition,
177
+ },
178
+ };
179
+ });
180
+ const remove = Effect.fn("ScheduleManager.remove")(function* (input = {}) {
181
+ const desired = yield* definition(input);
182
+ const before = yield* machine.inspectSchedulerJob(desired.definition);
183
+ if (!before.installed)
184
+ return { change: "unchanged" };
185
+ yield* machine.removeSchedulerJob(desired.definition);
186
+ const after = yield* machine.inspectSchedulerJob(desired.definition);
187
+ if (after.installed) {
188
+ return yield* new ScheduleVerificationError({
189
+ operation: "remove",
190
+ state: stateOf(after.installed, after.enabled, after.matches),
191
+ message: "native scheduler still reports the schedule as installed",
192
+ });
193
+ }
194
+ return { change: "removed" };
195
+ });
196
+ return ScheduleManager.of({
197
+ install: upsert,
198
+ inspect,
199
+ snapshot,
200
+ restore,
201
+ update: upsert,
202
+ status: inspect,
203
+ remove,
204
+ });
205
+ }));
@@ -0,0 +1,3 @@
1
+ import { Context } from "effect";
2
+ export class ScheduleManager extends Context.Service()("canonfig/schedule/ScheduleManager") {
3
+ }
@@ -0,0 +1,114 @@
1
+ import { Schema } from "effect";
2
+ export const scheduleWeekdays = [
3
+ "Mon",
4
+ "Tue",
5
+ "Wed",
6
+ "Thu",
7
+ "Fri",
8
+ "Sat",
9
+ "Sun",
10
+ ];
11
+ const isScheduleWeekday = (value) => scheduleWeekdays.some((candidate) => candidate === value);
12
+ export const SyncScheduleSchema = Schema.Union([
13
+ Schema.Struct({
14
+ kind: Schema.Literal("daily"),
15
+ localTime: Schema.NonEmptyString,
16
+ timezone: Schema.optional(Schema.NonEmptyString),
17
+ }),
18
+ Schema.Struct({
19
+ kind: Schema.Literal("weekly"),
20
+ weekdays: Schema.Array(Schema.Literals(scheduleWeekdays)),
21
+ localTime: Schema.NonEmptyString,
22
+ timezone: Schema.optional(Schema.NonEmptyString),
23
+ }),
24
+ // Accept v2 schedules written before multi-day weekly schedules were
25
+ // introduced. Normalization below converts this shape to `weekdays`.
26
+ Schema.Struct({
27
+ kind: Schema.Literal("weekly"),
28
+ weekday: Schema.Literals(scheduleWeekdays),
29
+ localTime: Schema.NonEmptyString,
30
+ timezone: Schema.optional(Schema.NonEmptyString),
31
+ }),
32
+ Schema.Struct({
33
+ kind: Schema.Literal("custom"),
34
+ expression: Schema.NonEmptyString,
35
+ timezone: Schema.optional(Schema.NonEmptyString),
36
+ }),
37
+ ]);
38
+ export const defaultSyncSchedule = {
39
+ kind: "daily",
40
+ localTime: "00:00",
41
+ };
42
+ /** Convert the signed profile-level schedule contract to native scheduler input. */
43
+ export const syncScheduleFromDefault = (schedule) => {
44
+ const timezone = schedule.timezone === "local" ? undefined : schedule.timezone;
45
+ switch (schedule.type) {
46
+ case "daily":
47
+ return timezone === undefined
48
+ ? { kind: "daily", localTime: schedule.at }
49
+ : { kind: "daily", localTime: schedule.at, timezone };
50
+ case "weekly": {
51
+ const weekdays = schedule.days.map((value) => {
52
+ const weekday = `${value.slice(0, 1).toUpperCase()}${value.slice(1).toLowerCase()}`;
53
+ if (!isScheduleWeekday(weekday)) {
54
+ throw new Error(`unsupported schedule weekday: ${value}`);
55
+ }
56
+ return weekday;
57
+ });
58
+ const normalized = {
59
+ kind: "weekly",
60
+ weekdays: [...new Set(weekdays)].sort((left, right) => weekdayIndex.get(left) - weekdayIndex.get(right)),
61
+ localTime: schedule.at,
62
+ };
63
+ return timezone === undefined ? normalized : { ...normalized, timezone };
64
+ }
65
+ case "custom":
66
+ return timezone === undefined
67
+ ? { kind: "custom", expression: schedule.expression }
68
+ : { kind: "custom", expression: schedule.expression, timezone };
69
+ }
70
+ };
71
+ const weekdayIndex = new Map(scheduleWeekdays.map((weekday, index) => [weekday, index]));
72
+ export const scheduleWeekdaysFor = (schedule) => "weekdays" in schedule
73
+ ? [...new Set(schedule.weekdays)].sort((left, right) => weekdayIndex.get(left) - weekdayIndex.get(right))
74
+ : [schedule.weekday];
75
+ export const normalizeSyncSchedule = (schedule) => {
76
+ if (schedule.kind !== "weekly")
77
+ return schedule;
78
+ const normalized = {
79
+ kind: "weekly",
80
+ weekdays: scheduleWeekdaysFor(schedule),
81
+ localTime: schedule.localTime,
82
+ };
83
+ return schedule.timezone === undefined
84
+ ? normalized
85
+ : { ...normalized, timezone: schedule.timezone };
86
+ };
87
+ export const syncScheduleFromResourceSpec = (spec) => {
88
+ const timezone = spec.timezone === "local" ? undefined : spec.timezone;
89
+ switch (spec.calendar.type) {
90
+ case "daily":
91
+ return { kind: "daily", localTime: spec.calendar.at, timezone };
92
+ case "weekly": {
93
+ const weekdays = spec.calendar.days.map((value) => {
94
+ const weekday = `${value.slice(0, 1).toUpperCase()}${value.slice(1).toLowerCase()}`;
95
+ if (!isScheduleWeekday(weekday)) {
96
+ throw new Error(`unsupported schedule weekday: ${value}`);
97
+ }
98
+ return weekday;
99
+ });
100
+ const normalized = {
101
+ kind: "weekly",
102
+ weekdays: [...new Set(weekdays)].sort((left, right) => weekdayIndex.get(left) - weekdayIndex.get(right)),
103
+ localTime: spec.calendar.at,
104
+ };
105
+ return timezone === undefined ? normalized : { ...normalized, timezone };
106
+ }
107
+ case "custom":
108
+ return {
109
+ kind: "custom",
110
+ expression: spec.calendar.expression,
111
+ timezone,
112
+ };
113
+ }
114
+ };
@@ -0,0 +1,25 @@
1
+ import { Effect } from "effect";
2
+ import { ScheduleHumanActionRequiredError } from "./schedule-manager.errors.js";
3
+ import { normalizeSyncSchedule, } from "./schedule-manager.types.js";
4
+ export const windowsCalendar = (schedule) => {
5
+ schedule = normalizeSyncSchedule(schedule);
6
+ if (schedule.kind === "custom") {
7
+ return Effect.fail(new ScheduleHumanActionRequiredError({
8
+ action: "use a daily or weekly schedule on Windows",
9
+ recovery: "Task Scheduler does not support the requested custom calendar expression. Choose a daily or weekly schedule, then retry.",
10
+ }));
11
+ }
12
+ if (schedule.timezone !== undefined) {
13
+ return Effect.fail(new ScheduleHumanActionRequiredError({
14
+ action: "use the Windows follower timezone for scheduled sync",
15
+ recovery: "Task Scheduler calendar triggers follow the Windows user timezone and cannot preserve a named IANA timezone across DST. Remove the explicit timezone or change the follower timezone.",
16
+ }));
17
+ }
18
+ return Effect.succeed(schedule.kind === "daily"
19
+ ? { kind: "daily", localTime: schedule.localTime }
20
+ : {
21
+ kind: "weekly",
22
+ weekdays: schedule.weekdays,
23
+ localTime: schedule.localTime,
24
+ });
25
+ };
@@ -0,0 +1,55 @@
1
+ import { Schema } from "effect";
2
+ export class RepositorySqlError extends Schema.TaggedError()("RepositorySqlError", {
3
+ operation: Schema.String,
4
+ message: Schema.String,
5
+ }) {
6
+ }
7
+ export class RepositoryDecodeError extends Schema.TaggedError()("RepositoryDecodeError", {
8
+ entity: Schema.String,
9
+ id: Schema.String,
10
+ message: Schema.String,
11
+ }) {
12
+ }
13
+ export class RevisionImmutableError extends Schema.TaggedError()("RevisionImmutableError", {
14
+ revision: Schema.String,
15
+ message: Schema.String,
16
+ }) {
17
+ }
18
+ export class ActiveRunExistsError extends Schema.TaggedError()("ActiveRunExistsError", {
19
+ follower: Schema.String,
20
+ }) {
21
+ }
22
+ export class FollowerNotFoundError extends Schema.TaggedError()("FollowerNotFoundError", {
23
+ follower: Schema.String,
24
+ }) {
25
+ }
26
+ export class RevisionNotFoundError extends Schema.TaggedError()("RevisionNotFoundError", {
27
+ revision: Schema.String,
28
+ }) {
29
+ }
30
+ export class RunNotFoundError extends Schema.TaggedError()("RunNotFoundError", {
31
+ run: Schema.String,
32
+ }) {
33
+ }
34
+ export class ActionNotInPlanError extends Schema.TaggedError()("ActionNotInPlanError", {
35
+ run: Schema.String,
36
+ action: Schema.String,
37
+ }) {
38
+ }
39
+ export class InvalidRunTransitionError extends Schema.TaggedError()("InvalidRunTransitionError", {
40
+ run: Schema.String,
41
+ message: Schema.String,
42
+ }) {
43
+ }
44
+ export class EnrollmentStateConflictError extends Schema.TaggedError()("EnrollmentStateConflictError", {
45
+ reason: Schema.Literals([
46
+ "invitation-not-found",
47
+ "invitation-used",
48
+ "invitation-expired",
49
+ "invitation-mismatch",
50
+ "follower-identity-conflict",
51
+ "credential-conflict",
52
+ ]),
53
+ message: Schema.String,
54
+ }) {
55
+ }