@knpkv/codecommit-core 0.5.1 → 0.6.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/AwsClient/AwsClientGated.d.ts +27 -0
- package/dist/AwsClient/AwsClientGated.d.ts.map +1 -0
- package/dist/AwsClient/AwsClientGated.js +105 -0
- package/dist/AwsClient/AwsClientGated.js.map +1 -0
- package/dist/CacheService/Database.d.ts.map +1 -1
- package/dist/CacheService/Database.js +5 -1
- package/dist/CacheService/Database.js.map +1 -1
- package/dist/CacheService/EventsHub.d.ts +44 -4
- package/dist/CacheService/EventsHub.d.ts.map +1 -1
- package/dist/CacheService/EventsHub.js.map +1 -1
- package/dist/CacheService/migrations/0011_audit_log.d.ts +5 -0
- package/dist/CacheService/migrations/0011_audit_log.d.ts.map +1 -0
- package/dist/CacheService/migrations/0011_audit_log.js +19 -0
- package/dist/CacheService/migrations/0011_audit_log.js.map +1 -0
- package/dist/CacheService/migrations/0012_audit_log_indexes.d.ts +5 -0
- package/dist/CacheService/migrations/0012_audit_log_indexes.d.ts.map +1 -0
- package/dist/CacheService/migrations/0012_audit_log_indexes.js +7 -0
- package/dist/CacheService/migrations/0012_audit_log_indexes.js.map +1 -0
- package/dist/Errors.d.ts +14 -1
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js +10 -0
- package/dist/Errors.js.map +1 -1
- package/dist/PermissionService/AuditLog.d.ts +62 -0
- package/dist/PermissionService/AuditLog.d.ts.map +1 -0
- package/dist/PermissionService/AuditLog.js +113 -0
- package/dist/PermissionService/AuditLog.js.map +1 -0
- package/dist/PermissionService/PermissionGate.d.ts +47 -0
- package/dist/PermissionService/PermissionGate.d.ts.map +1 -0
- package/dist/PermissionService/PermissionGate.js +14 -0
- package/dist/PermissionService/PermissionGate.js.map +1 -0
- package/dist/PermissionService/PermissionGateLive.d.ts +41 -0
- package/dist/PermissionService/PermissionGateLive.d.ts.map +1 -0
- package/dist/PermissionService/PermissionGateLive.js +83 -0
- package/dist/PermissionService/PermissionGateLive.js.map +1 -0
- package/dist/PermissionService/index.d.ts +39 -0
- package/dist/PermissionService/index.d.ts.map +1 -0
- package/dist/PermissionService/index.js +87 -0
- package/dist/PermissionService/index.js.map +1 -0
- package/dist/PermissionService/operations.d.ts +40 -0
- package/dist/PermissionService/operations.d.ts.map +1 -0
- package/dist/PermissionService/operations.js +38 -0
- package/dist/PermissionService/operations.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title AwsClientGated — transparent permission proxy
|
|
3
|
+
*
|
|
4
|
+
* Wraps every AwsClient method with permission check + audit logging.
|
|
5
|
+
* Returns the same `AwsClient.Service` type — callers don't know it exists.
|
|
6
|
+
*
|
|
7
|
+
* Two patterns:
|
|
8
|
+
* 1. InnerAwsClient tag — holds the real implementation, avoids circular dep
|
|
9
|
+
* 2. Service capture at Layer construction — all services yielded once,
|
|
10
|
+
* closed over in gate/wrapEffect/wrapStream, no R leakage
|
|
11
|
+
*
|
|
12
|
+
* PermissionDeniedError → AwsApiError at the boundary for type transparency.
|
|
13
|
+
* The actual PermissionDeniedError is preserved as the AwsApiError's `cause`.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import { Context, Layer } from "effect";
|
|
18
|
+
import { AuditLogRepo } from "../PermissionService/AuditLog.js";
|
|
19
|
+
import { PermissionService } from "../PermissionService/index.js";
|
|
20
|
+
import { PermissionGate } from "../PermissionService/PermissionGate.js";
|
|
21
|
+
import { AwsClient } from "./index.js";
|
|
22
|
+
declare const InnerAwsClient_base: Context.TagClass<InnerAwsClient, "@knpkv/codecommit-core/InnerAwsClient", AwsClient.Service>;
|
|
23
|
+
export declare class InnerAwsClient extends InnerAwsClient_base {
|
|
24
|
+
}
|
|
25
|
+
export declare const AwsClientGatedLive: Layer.Layer<AwsClient, never, InnerAwsClient | PermissionService | PermissionGate | AuditLogRepo>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=AwsClientGated.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsClientGated.d.ts","sourceRoot":"","sources":["../../src/AwsClient/AwsClientGated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,OAAO,EAAU,KAAK,EAAiB,MAAM,QAAQ,CAAA;AAG9D,OAAO,EAAE,YAAY,EAAyB,MAAM,kCAAkC,CAAA;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAA;AAEjE,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAA;AACvE,OAAO,EAAE,SAAS,EAAuB,MAAM,YAAY,CAAA;;AAG3D,qBAAa,cAAe,SAAQ,mBAGjC;CAAG;AAiBN,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,KAAK,CAC1C,SAAS,EACT,KAAK,EACL,cAAc,GAAG,iBAAiB,GAAG,cAAc,GAAG,YAAY,CAmKnE,CAAA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title AwsClientGated — transparent permission proxy
|
|
3
|
+
*
|
|
4
|
+
* Wraps every AwsClient method with permission check + audit logging.
|
|
5
|
+
* Returns the same `AwsClient.Service` type — callers don't know it exists.
|
|
6
|
+
*
|
|
7
|
+
* Two patterns:
|
|
8
|
+
* 1. InnerAwsClient tag — holds the real implementation, avoids circular dep
|
|
9
|
+
* 2. Service capture at Layer construction — all services yielded once,
|
|
10
|
+
* closed over in gate/wrapEffect/wrapStream, no R leakage
|
|
11
|
+
*
|
|
12
|
+
* PermissionDeniedError → AwsApiError at the boundary for type transparency.
|
|
13
|
+
* The actual PermissionDeniedError is preserved as the AwsApiError's `cause`.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import { Context, Effect, Layer, Match, Stream } from "effect";
|
|
18
|
+
import { AwsApiError, PermissionDeniedError } from "../Errors.js";
|
|
19
|
+
import { AuditLogRepo } from "../PermissionService/AuditLog.js";
|
|
20
|
+
import { PermissionService } from "../PermissionService/index.js";
|
|
21
|
+
import { getOperationMeta } from "../PermissionService/operations.js";
|
|
22
|
+
import { PermissionGate } from "../PermissionService/PermissionGate.js";
|
|
23
|
+
import { AwsClient } from "./index.js";
|
|
24
|
+
// Layer composition: AwsClientLive → InnerAwsClient (rename) → AwsClientGated → AwsClient
|
|
25
|
+
export class InnerAwsClient extends Context.Tag("@knpkv/codecommit-core/InnerAwsClient")() {
|
|
26
|
+
}
|
|
27
|
+
const toDeniedError = (p, reason) => new AwsApiError({
|
|
28
|
+
operation: p.operation,
|
|
29
|
+
profile: p.accountProfile,
|
|
30
|
+
region: p.region,
|
|
31
|
+
cause: new PermissionDeniedError({ operation: p.operation, reason })
|
|
32
|
+
});
|
|
33
|
+
export const AwsClientGatedLive = Layer.effect(AwsClient, Effect.gen(function* () {
|
|
34
|
+
const inner = yield* InnerAwsClient;
|
|
35
|
+
const permService = yield* PermissionService;
|
|
36
|
+
const gateService = yield* PermissionGate;
|
|
37
|
+
const auditLog = yield* AuditLogRepo;
|
|
38
|
+
// --- Core gate logic (captured services, no R leakage) ---
|
|
39
|
+
// Reads auditEnabled dynamically from Ref on each call —
|
|
40
|
+
// toggling audit in settings takes effect without restart
|
|
41
|
+
const logAudit = (params, permissionState, durationMs) => permService.isAuditEnabled().pipe(Effect.flatMap((enabled) => enabled
|
|
42
|
+
? auditLog.log({
|
|
43
|
+
timestamp: new Date().toISOString(),
|
|
44
|
+
operation: params.operation,
|
|
45
|
+
accountProfile: params.accountProfile,
|
|
46
|
+
region: params.region,
|
|
47
|
+
permissionState,
|
|
48
|
+
context: params.context,
|
|
49
|
+
durationMs
|
|
50
|
+
})
|
|
51
|
+
: Effect.void), Effect.catchAll(() => Effect.void));
|
|
52
|
+
const promptUser = (params) => Effect.gen(function* () {
|
|
53
|
+
const meta = getOperationMeta(params.operation);
|
|
54
|
+
const response = yield* gateService.request({
|
|
55
|
+
id: globalThis.crypto.randomUUID(),
|
|
56
|
+
operation: params.operation,
|
|
57
|
+
category: meta.category,
|
|
58
|
+
context: params.context
|
|
59
|
+
}).pipe(Effect.mapError(() => toDeniedError(params, "timeout")));
|
|
60
|
+
return yield* Match.value(response).pipe(Match.when("always_allow", () => permService.set(params.operation, "always_allow").pipe(Effect.as("always_allowed"))), Match.when("deny", () => Effect.gen(function* () {
|
|
61
|
+
yield* permService.set(params.operation, "deny");
|
|
62
|
+
yield* logAudit(params, "denied", null);
|
|
63
|
+
return yield* toDeniedError(params, "denied");
|
|
64
|
+
})), Match.when("allow_once", () => Effect.succeed("allowed")), Match.exhaustive);
|
|
65
|
+
});
|
|
66
|
+
const checkPermission = (params) => Effect.gen(function* () {
|
|
67
|
+
const state = yield* permService.check(params.operation);
|
|
68
|
+
return yield* Match.value(state).pipe(Match.when("always_allow", () => Effect.succeed("always_allowed")), Match.when("deny", () => logAudit(params, "denied", null).pipe(Effect.zipRight(toDeniedError(params, "denied")))), Match.when("allow", () => promptUser(params)), Match.exhaustive);
|
|
69
|
+
});
|
|
70
|
+
// --- Declarative wrapping: gated(op, ctx, acct, method) → wrapped method ---
|
|
71
|
+
// P inferred from `method` (last arg) — `acct` and `ctx` just extract strings
|
|
72
|
+
const gated = (op, ctx, acct, method) => (params) => {
|
|
73
|
+
const a = acct(params);
|
|
74
|
+
const g = { operation: op, context: ctx(params), accountProfile: a.profile, region: a.region };
|
|
75
|
+
return Effect.gen(function* () {
|
|
76
|
+
const ps = yield* checkPermission(g);
|
|
77
|
+
const start = Date.now();
|
|
78
|
+
const result = yield* method(params);
|
|
79
|
+
yield* logAudit(g, ps, Date.now() - start);
|
|
80
|
+
return result;
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const gatedStream = (op, ctx, acct, method) => (params) => {
|
|
84
|
+
const a = acct(params);
|
|
85
|
+
const g = { operation: op, context: ctx(params), accountProfile: a.profile, region: a.region };
|
|
86
|
+
return Stream.unwrap(checkPermission(g).pipe(Effect.map((ps) => {
|
|
87
|
+
const start = Date.now();
|
|
88
|
+
return method(params).pipe(Stream.onDone(() => logAudit(g, ps, Date.now() - start)));
|
|
89
|
+
})));
|
|
90
|
+
};
|
|
91
|
+
const self = (a) => a;
|
|
92
|
+
const nested = (p) => p.account;
|
|
93
|
+
return {
|
|
94
|
+
getPullRequests: gatedStream("getPullRequests", (a) => `List PRs for ${a.profile}`, self, (a) => inner.getPullRequests(a)),
|
|
95
|
+
getCallerIdentity: gated("getCallerIdentity", (a) => `Get identity for ${a.profile}`, self, inner.getCallerIdentity),
|
|
96
|
+
createPullRequest: gated("createPullRequest", (p) => `Create PR on ${p.repositoryName}`, nested, inner.createPullRequest),
|
|
97
|
+
listBranches: gated("listBranches", (p) => `List branches in ${p.repositoryName}`, nested, inner.listBranches),
|
|
98
|
+
getCommentsForPullRequest: gated("getCommentsForPullRequest", (p) => `Comments for PR #${p.pullRequestId}`, nested, inner.getCommentsForPullRequest),
|
|
99
|
+
updatePullRequestTitle: gated("updatePullRequestTitle", (p) => `Edit title of PR #${p.pullRequestId}`, nested, inner.updatePullRequestTitle),
|
|
100
|
+
updatePullRequestDescription: gated("updatePullRequestDescription", (p) => `Edit desc of PR #${p.pullRequestId}`, nested, inner.updatePullRequestDescription),
|
|
101
|
+
getPullRequest: gated("getPullRequest", (p) => `Fetch PR #${p.pullRequestId}`, nested, inner.getPullRequest),
|
|
102
|
+
getDifferences: gated("getDifferences", (p) => `Diff for ${p.repositoryName}`, nested, inner.getDifferences)
|
|
103
|
+
};
|
|
104
|
+
}));
|
|
105
|
+
//# sourceMappingURL=AwsClientGated.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AwsClientGated.js","sourceRoot":"","sources":["../../src/AwsClient/AwsClientGated.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../src/CacheService/Database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAkB,KAAK,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../src/CacheService/Database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAkB,KAAK,EAAE,MAAM,QAAQ,CAAA;AA8B9C,eAAO,MAAM,UAAU,qJAMW,CAAA;AAElC,eAAO,MAAM,cAAc,wIAezB,CAAA;AAEF,eAAO,MAAM,YAAY,+NAAsD,CAAA"}
|
|
@@ -17,6 +17,8 @@ import migration0007 from "./migrations/0007_stats_columns.js";
|
|
|
17
17
|
import migration0008 from "./migrations/0008_merged_by.js";
|
|
18
18
|
import migration0009 from "./migrations/0009_approved_by.js";
|
|
19
19
|
import migration0010 from "./migrations/0010_commented_by.js";
|
|
20
|
+
import migration0011 from "./migrations/0011_audit_log.js";
|
|
21
|
+
import migration0012 from "./migrations/0012_audit_log_indexes.js";
|
|
20
22
|
const homeDir = Config.string("HOME").pipe(Config.orElse(() => Config.string("USERPROFILE")));
|
|
21
23
|
const dbUrl = homeDir.pipe(Config.map((h) => `file:${h}/.codecommit/cache.db`));
|
|
22
24
|
const EnsureDbDir = Layer.effectDiscard(Effect.gen(function* () {
|
|
@@ -39,7 +41,9 @@ export const MigrationsLive = LibsqlMigrator.layer({
|
|
|
39
41
|
"0007_stats_columns": migration0007,
|
|
40
42
|
"0008_merged_by": migration0008,
|
|
41
43
|
"0009_approved_by": migration0009,
|
|
42
|
-
"0010_commented_by": migration0010
|
|
44
|
+
"0010_commented_by": migration0010,
|
|
45
|
+
"0011_audit_log": migration0011,
|
|
46
|
+
"0012_audit_log_indexes": migration0012
|
|
43
47
|
})
|
|
44
48
|
});
|
|
45
49
|
export const DatabaseLive = MigrationsLive.pipe(Layer.provideMerge(LibsqlLive));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Database.js","sourceRoot":"","sources":["../../src/CacheService/Database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,KAAK,YAAY,MAAM,iCAAiC,CAAA;AAC/D,OAAO,KAAK,cAAc,MAAM,mCAAmC,CAAA;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAA;AAC9C,OAAO,aAAa,MAAM,8BAA8B,CAAA;AACxD,OAAO,aAAa,MAAM,8BAA8B,CAAA;AACxD,OAAO,aAAa,MAAM,uCAAuC,CAAA;AACjE,OAAO,aAAa,MAAM,0CAA0C,CAAA;AACpE,OAAO,aAAa,MAAM,oCAAoC,CAAA;AAC9D,OAAO,aAAa,MAAM,mCAAmC,CAAA;AAC7D,OAAO,aAAa,MAAM,oCAAoC,CAAA;AAC9D,OAAO,aAAa,MAAM,gCAAgC,CAAA;AAC1D,OAAO,aAAa,MAAM,kCAAkC,CAAA;AAC5D,OAAO,aAAa,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"Database.js","sourceRoot":"","sources":["../../src/CacheService/Database.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,8 @@ export type RepoChange = Data.TaggedEnum<{
|
|
|
8
8
|
AppState: {};
|
|
9
9
|
SystemNotifications: {};
|
|
10
10
|
Sandboxes: {};
|
|
11
|
+
PermissionRequired: {};
|
|
12
|
+
PermissionResolved: {};
|
|
11
13
|
}>;
|
|
12
14
|
export declare const RepoChange: {
|
|
13
15
|
readonly Comments: Data.Case.Constructor<{
|
|
@@ -34,7 +36,13 @@ export declare const RepoChange: {
|
|
|
34
36
|
readonly Sandboxes: Data.Case.Constructor<{
|
|
35
37
|
readonly _tag: "Sandboxes";
|
|
36
38
|
}, "_tag">;
|
|
37
|
-
readonly
|
|
39
|
+
readonly PermissionRequired: Data.Case.Constructor<{
|
|
40
|
+
readonly _tag: "PermissionRequired";
|
|
41
|
+
}, "_tag">;
|
|
42
|
+
readonly PermissionResolved: Data.Case.Constructor<{
|
|
43
|
+
readonly _tag: "PermissionResolved";
|
|
44
|
+
}, "_tag">;
|
|
45
|
+
readonly $is: <Tag extends "Comments" | "PullRequests" | "Notifications" | "Subscriptions" | "Config" | "AppState" | "SystemNotifications" | "Sandboxes" | "PermissionRequired" | "PermissionResolved">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
38
46
|
readonly _tag: "Comments";
|
|
39
47
|
}, {
|
|
40
48
|
readonly _tag: Tag;
|
|
@@ -66,6 +74,14 @@ export declare const RepoChange: {
|
|
|
66
74
|
readonly _tag: "Sandboxes";
|
|
67
75
|
}, {
|
|
68
76
|
readonly _tag: Tag;
|
|
77
|
+
}> | Extract<{
|
|
78
|
+
readonly _tag: "PermissionRequired";
|
|
79
|
+
}, {
|
|
80
|
+
readonly _tag: Tag;
|
|
81
|
+
}> | Extract<{
|
|
82
|
+
readonly _tag: "PermissionResolved";
|
|
83
|
+
}, {
|
|
84
|
+
readonly _tag: Tag;
|
|
69
85
|
}>;
|
|
70
86
|
readonly $match: {
|
|
71
87
|
<const Cases extends {
|
|
@@ -93,7 +109,13 @@ export declare const RepoChange: {
|
|
|
93
109
|
readonly Sandboxes: (args: {
|
|
94
110
|
readonly _tag: "Sandboxes";
|
|
95
111
|
}) => any;
|
|
96
|
-
|
|
112
|
+
readonly PermissionRequired: (args: {
|
|
113
|
+
readonly _tag: "PermissionRequired";
|
|
114
|
+
}) => any;
|
|
115
|
+
readonly PermissionResolved: (args: {
|
|
116
|
+
readonly _tag: "PermissionResolved";
|
|
117
|
+
}) => any;
|
|
118
|
+
}>(cases: Cases & { [K in Exclude<keyof Cases, "Comments" | "PullRequests" | "Notifications" | "Subscriptions" | "Config" | "AppState" | "SystemNotifications" | "Sandboxes" | "PermissionRequired" | "PermissionResolved">]: never; }): (value: {
|
|
97
119
|
readonly _tag: "Comments";
|
|
98
120
|
} | {
|
|
99
121
|
readonly _tag: "PullRequests";
|
|
@@ -109,7 +131,11 @@ export declare const RepoChange: {
|
|
|
109
131
|
readonly _tag: "SystemNotifications";
|
|
110
132
|
} | {
|
|
111
133
|
readonly _tag: "Sandboxes";
|
|
112
|
-
}
|
|
134
|
+
} | {
|
|
135
|
+
readonly _tag: "PermissionRequired";
|
|
136
|
+
} | {
|
|
137
|
+
readonly _tag: "PermissionResolved";
|
|
138
|
+
}) => import("effect/Unify").Unify<ReturnType<Cases["Comments" | "PullRequests" | "Notifications" | "Subscriptions" | "Config" | "AppState" | "SystemNotifications" | "Sandboxes" | "PermissionRequired" | "PermissionResolved"]>>;
|
|
113
139
|
<const Cases extends {
|
|
114
140
|
readonly Comments: (args: {
|
|
115
141
|
readonly _tag: "Comments";
|
|
@@ -135,6 +161,12 @@ export declare const RepoChange: {
|
|
|
135
161
|
readonly Sandboxes: (args: {
|
|
136
162
|
readonly _tag: "Sandboxes";
|
|
137
163
|
}) => any;
|
|
164
|
+
readonly PermissionRequired: (args: {
|
|
165
|
+
readonly _tag: "PermissionRequired";
|
|
166
|
+
}) => any;
|
|
167
|
+
readonly PermissionResolved: (args: {
|
|
168
|
+
readonly _tag: "PermissionResolved";
|
|
169
|
+
}) => any;
|
|
138
170
|
}>(value: {
|
|
139
171
|
readonly _tag: "Comments";
|
|
140
172
|
} | {
|
|
@@ -151,7 +183,11 @@ export declare const RepoChange: {
|
|
|
151
183
|
readonly _tag: "SystemNotifications";
|
|
152
184
|
} | {
|
|
153
185
|
readonly _tag: "Sandboxes";
|
|
154
|
-
}
|
|
186
|
+
} | {
|
|
187
|
+
readonly _tag: "PermissionRequired";
|
|
188
|
+
} | {
|
|
189
|
+
readonly _tag: "PermissionResolved";
|
|
190
|
+
}, cases: Cases & { [K in Exclude<keyof Cases, "Comments" | "PullRequests" | "Notifications" | "Subscriptions" | "Config" | "AppState" | "SystemNotifications" | "Sandboxes" | "PermissionRequired" | "PermissionResolved">]: never; }): import("effect/Unify").Unify<ReturnType<Cases["Comments" | "PullRequests" | "Notifications" | "Subscriptions" | "Config" | "AppState" | "SystemNotifications" | "Sandboxes" | "PermissionRequired" | "PermissionResolved"]>>;
|
|
155
191
|
};
|
|
156
192
|
};
|
|
157
193
|
declare const EventsHub_base: Effect.Service.Class<EventsHub, "EventsHub", {
|
|
@@ -174,6 +210,10 @@ declare const EventsHub_base: Effect.Service.Class<EventsHub, "EventsHub", {
|
|
|
174
210
|
readonly _tag: "SystemNotifications";
|
|
175
211
|
} | {
|
|
176
212
|
readonly _tag: "Sandboxes";
|
|
213
|
+
} | {
|
|
214
|
+
readonly _tag: "PermissionRequired";
|
|
215
|
+
} | {
|
|
216
|
+
readonly _tag: "PermissionResolved";
|
|
177
217
|
}, never, never>;
|
|
178
218
|
}, never, never>;
|
|
179
219
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventsHub.d.ts","sourceRoot":"","sources":["../../src/CacheService/EventsHub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACvC,YAAY,EAAE,EAAE,CAAA;IAChB,aAAa,EAAE,EAAE,CAAA;IACjB,aAAa,EAAE,EAAE,CAAA;IACjB,QAAQ,EAAE,EAAE,CAAA;IACZ,MAAM,EAAE,EAAE,CAAA;IACV,QAAQ,EAAE,EAAE,CAAA;IACZ,mBAAmB,EAAE,EAAE,CAAA;IACvB,SAAS,EAAE,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"EventsHub.d.ts","sourceRoot":"","sources":["../../src/CacheService/EventsHub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;IACvC,YAAY,EAAE,EAAE,CAAA;IAChB,aAAa,EAAE,EAAE,CAAA;IACjB,aAAa,EAAE,EAAE,CAAA;IACjB,QAAQ,EAAE,EAAE,CAAA;IACZ,MAAM,EAAE,EAAE,CAAA;IACV,QAAQ,EAAE,EAAE,CAAA;IACZ,mBAAmB,EAAE,EAAE,CAAA;IACvB,SAAS,EAAE,EAAE,CAAA;IACb,kBAAkB,EAAE,EAAE,CAAA;IACtB,kBAAkB,EAAE,EAAE,CAAA;CACvB,CAAC,CAAA;AAEF,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAgC,CAAA;;;0BAS1B,UAAU,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;gBAS1C,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;AAhBnF,qBAAa,SAAU,SAAQ,cAyC7B;CAAG"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventsHub.js","sourceRoot":"","sources":["../../src/CacheService/EventsHub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;
|
|
1
|
+
{"version":3,"file":"EventsHub.js","sourceRoot":"","sources":["../../src/CacheService/EventsHub.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAe1D,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAc,CAAA;AAEvD,MAAM,OAAO,SAAU,SAAQ,MAAM,CAAC,OAAO,EAAa,CAAC,WAAW,EAAE;IACtE,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1B,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,EAAc,CAAA;QACpD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC1C,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,EAAsB,CAAC,CAAA;QACrE,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;QAErD,MAAM,OAAO,GAAG,CAAC,MAAkB,EAAuB,EAAE,CAC1D,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CACvB,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,CAC1B,QAAQ;YACN,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAChE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CACvD,CACF,CAAA;QAEH,MAAM,KAAK,GAAG,CAAU,MAA8B,EAA0B,EAAE,CAChF,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,CAC3B,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,IAAI,CAC7B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,GAAG,EAAsB,CAAC,CAAC,EACvE,MAAM,CAAC,QAAQ,CACb,MAAM,CAAC,QAAQ,CACb,MAAM,EACN,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;YAC3C,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;YAClC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CACnB,CAAC,GAAG,IAAI,CAAC,EACT,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAClD,EAAE,OAAO,EAAE,IAAI,EAAE,CAClB,CAAA;QACH,CAAC,CAAC,CACH,CACF,CACF,CACF,CAAA;QAEH,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAA;QAE3C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;IACtC,CAAC,CAAC;CACH,CAAC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0011_audit_log.d.ts","sourceRoot":"","sources":["../../../src/CacheService/migrations/0011_audit_log.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;;AAEvC,wBAmBC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as SqlClient from "@effect/sql/SqlClient";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
export default Effect.flatMap(SqlClient.SqlClient, (sql) => Effect.all([
|
|
4
|
+
sql `CREATE TABLE IF NOT EXISTS audit_log (
|
|
5
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
6
|
+
timestamp TEXT NOT NULL DEFAULT (datetime('now')),
|
|
7
|
+
operation TEXT NOT NULL,
|
|
8
|
+
account_profile TEXT NOT NULL DEFAULT '',
|
|
9
|
+
region TEXT NOT NULL DEFAULT '',
|
|
10
|
+
permission_state TEXT NOT NULL,
|
|
11
|
+
context TEXT NOT NULL DEFAULT '',
|
|
12
|
+
duration_ms INTEGER
|
|
13
|
+
)`,
|
|
14
|
+
sql `CREATE INDEX IF NOT EXISTS idx_audit_log_timestamp ON audit_log(timestamp)`,
|
|
15
|
+
sql `CREATE INDEX IF NOT EXISTS idx_audit_log_operation ON audit_log(operation)`,
|
|
16
|
+
sql `CREATE INDEX IF NOT EXISTS idx_audit_log_permission_state ON audit_log(permission_state)`,
|
|
17
|
+
sql `CREATE INDEX IF NOT EXISTS idx_audit_log_account_profile ON audit_log(account_profile)`
|
|
18
|
+
]).pipe(Effect.asVoid, Effect.catchAll(() => Effect.void)));
|
|
19
|
+
//# sourceMappingURL=0011_audit_log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0011_audit_log.js","sourceRoot":"","sources":["../../../src/CacheService/migrations/0011_audit_log.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,eAAe,MAAM,CAAC,OAAO,CAC3B,SAAS,CAAC,SAAS,EACnB,CAAC,GAAG,EAAE,EAAE,CACN,MAAM,CAAC,GAAG,CAAC;IACT,GAAG,CAAA;;;;;;;;;QASD;IACF,GAAG,CAAA,4EAA4E;IAC/E,GAAG,CAAA,4EAA4E;IAC/E,GAAG,CAAA,0FAA0F;IAC7F,GAAG,CAAA,wFAAwF;CAC5F,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAC7D,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0012_audit_log_indexes.d.ts","sourceRoot":"","sources":["../../../src/CacheService/migrations/0012_audit_log_indexes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;;AAEvC,wBAOC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as SqlClient from "@effect/sql/SqlClient";
|
|
2
|
+
import * as Effect from "effect/Effect";
|
|
3
|
+
export default Effect.flatMap(SqlClient.SqlClient, (sql) => Effect.all([
|
|
4
|
+
sql `CREATE INDEX IF NOT EXISTS idx_audit_log_permission_state ON audit_log(permission_state)`,
|
|
5
|
+
sql `CREATE INDEX IF NOT EXISTS idx_audit_log_account_profile ON audit_log(account_profile)`
|
|
6
|
+
]).pipe(Effect.asVoid, Effect.catchAll(() => Effect.void)));
|
|
7
|
+
//# sourceMappingURL=0012_audit_log_indexes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"0012_audit_log_indexes.js","sourceRoot":"","sources":["../../../src/CacheService/migrations/0012_audit_log_indexes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAClD,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC,eAAe,MAAM,CAAC,OAAO,CAC3B,SAAS,CAAC,SAAS,EACnB,CAAC,GAAG,EAAE,EAAE,CACN,MAAM,CAAC,GAAG,CAAC;IACT,GAAG,CAAA,0FAA0F;IAC7F,GAAG,CAAA,wFAAwF;CAC5F,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAC7D,CAAA"}
|
package/dist/Errors.d.ts
CHANGED
|
@@ -146,6 +146,19 @@ declare const SandboxError_base: Schema.TaggedErrorClass<SandboxError, "SandboxE
|
|
|
146
146
|
*/
|
|
147
147
|
export declare class SandboxError extends SandboxError_base {
|
|
148
148
|
}
|
|
149
|
+
declare const PermissionDeniedError_base: Schema.TaggedErrorClass<PermissionDeniedError, "PermissionDeniedError", {
|
|
150
|
+
readonly _tag: Schema.tag<"PermissionDeniedError">;
|
|
151
|
+
} & {
|
|
152
|
+
operation: typeof Schema.String;
|
|
153
|
+
reason: Schema.Literal<["denied", "timeout"]>;
|
|
154
|
+
}>;
|
|
155
|
+
/**
|
|
156
|
+
* API call blocked by permission gate.
|
|
157
|
+
*
|
|
158
|
+
* @category Errors
|
|
159
|
+
*/
|
|
160
|
+
export declare class PermissionDeniedError extends PermissionDeniedError_base {
|
|
161
|
+
}
|
|
149
162
|
/**
|
|
150
163
|
* Union of errors from AwsClient methods.
|
|
151
164
|
*
|
|
@@ -157,6 +170,6 @@ export type AwsClientError = AwsCredentialError | AwsThrottleError | AwsApiError
|
|
|
157
170
|
*
|
|
158
171
|
* @category Errors
|
|
159
172
|
*/
|
|
160
|
-
export type CodeCommitError = AwsCredentialError | AwsThrottleError | AwsApiError | ConfigError | ConfigParseError | ProfileDetectionError | RefreshError | DockerError | SandboxError;
|
|
173
|
+
export type CodeCommitError = AwsCredentialError | AwsThrottleError | AwsApiError | ConfigError | ConfigParseError | ProfileDetectionError | RefreshError | DockerError | SandboxError | PermissionDeniedError;
|
|
161
174
|
export {};
|
|
162
175
|
//# sourceMappingURL=Errors.d.ts.map
|
package/dist/Errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../src/Errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;;;;;;;;AAG/B;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,uBAOvC;CAAG;;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,qBAOrC;CAAG;;;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAQhC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAMhC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,qBAMrC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,0BAM1C;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,iBAMjC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAMhC;CAAG;;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,iBAOjC;CAAG;AAEJ;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,WAAW,CAAA;AAEhF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB,kBAAkB,GAClB,gBAAgB,GAChB,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,qBAAqB,GACrB,YAAY,GACZ,WAAW,GACX,YAAY,CAAA"}
|
|
1
|
+
{"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../src/Errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;;;;;;;;AAG/B;;;;GAIG;AACH,qBAAa,kBAAmB,SAAQ,uBAOvC;CAAG;;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,qBAOrC;CAAG;;;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAQhC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAMhC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,gBAAiB,SAAQ,qBAMrC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,0BAM1C;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,iBAMjC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,gBAMhC;CAAG;;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,iBAOjC;CAAG;;;;;;;AAEJ;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,0BAM1C;CAAG;AAEJ;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,kBAAkB,GAAG,gBAAgB,GAAG,WAAW,CAAA;AAEhF;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB,kBAAkB,GAClB,gBAAgB,GAChB,WAAW,GACX,WAAW,GACX,gBAAgB,GAChB,qBAAqB,GACrB,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,qBAAqB,CAAA"}
|
package/dist/Errors.js
CHANGED
|
@@ -120,4 +120,14 @@ export class SandboxError extends Schema.TaggedError()("SandboxError", {
|
|
|
120
120
|
cause: Schema.optional(Schema.Defect)
|
|
121
121
|
}) {
|
|
122
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* API call blocked by permission gate.
|
|
125
|
+
*
|
|
126
|
+
* @category Errors
|
|
127
|
+
*/
|
|
128
|
+
export class PermissionDeniedError extends Schema.TaggedError()("PermissionDeniedError", {
|
|
129
|
+
operation: Schema.String,
|
|
130
|
+
reason: Schema.Literal("denied", "timeout")
|
|
131
|
+
}) {
|
|
132
|
+
}
|
|
123
133
|
//# sourceMappingURL=Errors.js.map
|
package/dist/Errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Errors.js","sourceRoot":"","sources":["../src/Errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAElE;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,oBAAoB,EACpB;IACE,OAAO,EAAE,cAAc;IACvB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAC1E,kBAAkB,EAClB;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,UAAU,EAAE,MAAM,CAAC,MAAM;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,MAAM,CAAC,WAAW,EAAe,CAChE,aAAa,EACb;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,OAAO,EAAE,cAAc;IACvB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,MAAM,CAAC,WAAW,EAAe,CAChE,aAAa,EACb;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAC1E,kBAAkB,EAClB;IACE,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,MAAM,CAAC,WAAW,EAAyB,CACpF,uBAAuB,EACvB;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,EAAgB,CAClE,cAAc,EACd;IACE,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,MAAM,CAAC,WAAW,EAAe,CAChE,aAAa,EACb;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,EAAgB,CAClE,cAAc,EACd;IACE,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG"}
|
|
1
|
+
{"version":3,"file":"Errors.js","sourceRoot":"","sources":["../src/Errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAElE;;;;GAIG;AACH,MAAM,OAAO,kBAAmB,SAAQ,MAAM,CAAC,WAAW,EAAsB,CAC9E,oBAAoB,EACpB;IACE,OAAO,EAAE,cAAc;IACvB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAC1E,kBAAkB,EAClB;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,UAAU,EAAE,MAAM,CAAC,MAAM;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,MAAM,CAAC,WAAW,EAAe,CAChE,aAAa,EACb;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,OAAO,EAAE,cAAc;IACvB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,MAAM,CAAC,WAAW,EAAe,CAChE,aAAa,EACb;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,WAAW,EAAoB,CAC1E,kBAAkB,EAClB;IACE,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,KAAK,EAAE,MAAM,CAAC,MAAM;CACrB,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,MAAM,CAAC,WAAW,EAAyB,CACpF,uBAAuB,EACvB;IACE,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,EAAgB,CAClE,cAAc,EACd;IACE,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,MAAM,CAAC,WAAW,EAAe,CAChE,aAAa,EACb;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,MAAM,CAAC,WAAW,EAAgB,CAClE,cAAc,EACd;IACE,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC,MAAM;IACtB,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CACF;CAAG;AAEJ;;;;GAIG;AACH,MAAM,OAAO,qBAAsB,SAAQ,MAAM,CAAC,WAAW,EAAyB,CACpF,uBAAuB,EACvB;IACE,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC;CAC5C,CACF;CAAG"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title AuditLogRepo — records every AWS API call
|
|
3
|
+
*
|
|
4
|
+
* Every call through the permission gate gets recorded — allowed, denied,
|
|
5
|
+
* or timed out.
|
|
6
|
+
*
|
|
7
|
+
* Design constraints:
|
|
8
|
+
* - MUST never block API calls (catchAll on write failures at call site)
|
|
9
|
+
* - MUST handle high volume (~17 ops per refresh × every 5min)
|
|
10
|
+
* - MUST auto-prune (150k entries/month without pruning)
|
|
11
|
+
* - MUST support filtered queries (for the audit log UI page)
|
|
12
|
+
*
|
|
13
|
+
* `durationMs` is null when the API call was denied/timed out (never ran).
|
|
14
|
+
* When present, it reflects actual AWS API latency — not permission prompt wait.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import * as SqlClient from "@effect/sql/SqlClient";
|
|
19
|
+
import { Effect, Schema } from "effect";
|
|
20
|
+
import { CacheError } from "../CacheService/CacheError.js";
|
|
21
|
+
export declare const AuditLogEntry: Schema.Struct<{
|
|
22
|
+
id: typeof Schema.Number;
|
|
23
|
+
timestamp: typeof Schema.String;
|
|
24
|
+
operation: typeof Schema.String;
|
|
25
|
+
accountProfile: typeof Schema.String;
|
|
26
|
+
region: typeof Schema.String;
|
|
27
|
+
permissionState: Schema.Literal<["allowed", "always_allowed", "denied", "timed_out"]>;
|
|
28
|
+
context: typeof Schema.String;
|
|
29
|
+
durationMs: Schema.NullOr<typeof Schema.Number>;
|
|
30
|
+
}>;
|
|
31
|
+
export type AuditLogEntry = typeof AuditLogEntry.Type;
|
|
32
|
+
export type NewAuditLogEntry = Omit<AuditLogEntry, "id">;
|
|
33
|
+
export interface PaginatedAuditLog {
|
|
34
|
+
readonly items: ReadonlyArray<AuditLogEntry>;
|
|
35
|
+
readonly total: number;
|
|
36
|
+
readonly nextCursor?: number;
|
|
37
|
+
}
|
|
38
|
+
declare const AuditLogRepo_base: Effect.Service.Class<AuditLogRepo, "AuditLogRepo", {
|
|
39
|
+
readonly dependencies: readonly [import("effect/Layer").Layer<SqlClient.SqlClient | import("@effect/sql-libsql/LibsqlClient").LibsqlClient, import("@effect/sql/SqlError").SqlError | import("effect/ConfigError").ConfigError | import("@effect/sql/Migrator").MigrationError, import("@effect/platform/FileSystem").FileSystem>];
|
|
40
|
+
readonly effect: Effect.Effect<{
|
|
41
|
+
log: (entry: NewAuditLogEntry) => Effect.Effect<void, CacheError, never>;
|
|
42
|
+
findAll: (opts?: {
|
|
43
|
+
readonly limit?: number | undefined;
|
|
44
|
+
readonly offset?: number | undefined;
|
|
45
|
+
readonly operation?: string | undefined;
|
|
46
|
+
readonly accountProfile?: string | undefined;
|
|
47
|
+
readonly permissionState?: string | undefined;
|
|
48
|
+
readonly from?: string | undefined;
|
|
49
|
+
readonly to?: string | undefined;
|
|
50
|
+
readonly search?: string | undefined;
|
|
51
|
+
}) => Effect.Effect<PaginatedAuditLog, CacheError>;
|
|
52
|
+
prune: (retentionDays: number) => Effect.Effect<number, CacheError>;
|
|
53
|
+
exportAll: (opts?: {
|
|
54
|
+
readonly from?: string | undefined;
|
|
55
|
+
readonly to?: string | undefined;
|
|
56
|
+
}) => Effect.Effect<ReadonlyArray<AuditLogEntry>, CacheError>;
|
|
57
|
+
}, never, SqlClient.SqlClient>;
|
|
58
|
+
}>;
|
|
59
|
+
export declare class AuditLogRepo extends AuditLogRepo_base {
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=AuditLog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditLog.d.ts","sourceRoot":"","sources":["../../src/PermissionService/AuditLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAA;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAG1D,eAAO,MAAM,aAAa;;;;;;;;;EASxB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AAErD,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAA;AAExD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,aAAa,CAAC,CAAA;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAC7B;;;;qBA6BkB,gBAAgB;yBAQZ;YACf,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACvC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAC5C,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAC7C,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SACrC,KAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,UAAU,CAAC;+BAuDzB,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;2BAY9C;YACjB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SACjC,KAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,UAAU,CAAC;;;AA5GjE,qBAAa,YAAa,SAAQ,iBA8HhC;CAAG"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title AuditLogRepo — records every AWS API call
|
|
3
|
+
*
|
|
4
|
+
* Every call through the permission gate gets recorded — allowed, denied,
|
|
5
|
+
* or timed out.
|
|
6
|
+
*
|
|
7
|
+
* Design constraints:
|
|
8
|
+
* - MUST never block API calls (catchAll on write failures at call site)
|
|
9
|
+
* - MUST handle high volume (~17 ops per refresh × every 5min)
|
|
10
|
+
* - MUST auto-prune (150k entries/month without pruning)
|
|
11
|
+
* - MUST support filtered queries (for the audit log UI page)
|
|
12
|
+
*
|
|
13
|
+
* `durationMs` is null when the API call was denied/timed out (never ran).
|
|
14
|
+
* When present, it reflects actual AWS API latency — not permission prompt wait.
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
import * as SqlClient from "@effect/sql/SqlClient";
|
|
19
|
+
import * as SqlSchema from "@effect/sql/SqlSchema";
|
|
20
|
+
import { Effect, Schema } from "effect";
|
|
21
|
+
import { CacheError } from "../CacheService/CacheError.js";
|
|
22
|
+
import { DatabaseLive } from "../CacheService/Database.js";
|
|
23
|
+
export const AuditLogEntry = Schema.Struct({
|
|
24
|
+
id: Schema.Number,
|
|
25
|
+
timestamp: Schema.String,
|
|
26
|
+
operation: Schema.String,
|
|
27
|
+
accountProfile: Schema.String,
|
|
28
|
+
region: Schema.String,
|
|
29
|
+
permissionState: Schema.Literal("allowed", "always_allowed", "denied", "timed_out"),
|
|
30
|
+
context: Schema.String,
|
|
31
|
+
durationMs: Schema.NullOr(Schema.Number)
|
|
32
|
+
});
|
|
33
|
+
const cacheError = (op) => (effect) => effect.pipe(Effect.mapError((cause) => new CacheError({ operation: `AuditLogRepo.${op}`, cause })), Effect.withSpan(`AuditLogRepo.${op}`, { captureStackTrace: false }));
|
|
34
|
+
export class AuditLogRepo extends Effect.Service()("AuditLogRepo", {
|
|
35
|
+
dependencies: [DatabaseLive],
|
|
36
|
+
effect: Effect.gen(function* () {
|
|
37
|
+
const sql = yield* SqlClient.SqlClient;
|
|
38
|
+
const findAll_ = SqlSchema.findAll({
|
|
39
|
+
Result: AuditLogEntry,
|
|
40
|
+
Request: Schema.Struct({
|
|
41
|
+
limit: Schema.Number,
|
|
42
|
+
offset: Schema.Number
|
|
43
|
+
}),
|
|
44
|
+
execute: (req) => sql `SELECT * FROM audit_log ORDER BY id DESC LIMIT ${req.limit} OFFSET ${req.offset}`
|
|
45
|
+
});
|
|
46
|
+
const countAll = SqlSchema.single({
|
|
47
|
+
Result: Schema.Struct({ count: Schema.Number }),
|
|
48
|
+
Request: Schema.Void,
|
|
49
|
+
execute: () => sql `SELECT count(*) as count FROM audit_log`
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
log: (entry) => sql `INSERT INTO audit_log (timestamp, operation, account_profile, region, permission_state, context, duration_ms)
|
|
53
|
+
VALUES (${entry.timestamp}, ${entry.operation}, ${entry.accountProfile}, ${entry.region}, ${entry.permissionState}, ${entry.context}, ${entry.durationMs})`
|
|
54
|
+
.pipe(Effect.asVoid, cacheError("log")),
|
|
55
|
+
findAll: (opts) => {
|
|
56
|
+
// Clamp numeric params to prevent injection via malformed input
|
|
57
|
+
const limit = Math.max(1, Math.min(200, Math.floor(opts?.limit ?? 50)));
|
|
58
|
+
const offset = Math.max(0, Math.floor(opts?.offset ?? 0));
|
|
59
|
+
// For filtered queries, build dynamic SQL
|
|
60
|
+
if (opts?.operation || opts?.accountProfile || opts?.permissionState || opts?.from || opts?.to || opts?.search) {
|
|
61
|
+
const conditions = [];
|
|
62
|
+
if (opts?.operation)
|
|
63
|
+
conditions.push(`operation = '${opts.operation.replace(/'/g, "''")}'`);
|
|
64
|
+
if (opts?.accountProfile) {
|
|
65
|
+
conditions.push(`account_profile = '${opts.accountProfile.replace(/'/g, "''")}'`);
|
|
66
|
+
}
|
|
67
|
+
if (opts?.permissionState) {
|
|
68
|
+
conditions.push(`permission_state = '${opts.permissionState.replace(/'/g, "''")}'`);
|
|
69
|
+
}
|
|
70
|
+
if (opts?.from)
|
|
71
|
+
conditions.push(`timestamp >= '${opts.from.replace(/'/g, "''")}'`);
|
|
72
|
+
if (opts?.to)
|
|
73
|
+
conditions.push(`timestamp <= '${opts.to.replace(/'/g, "''")}'`);
|
|
74
|
+
if (opts?.search) {
|
|
75
|
+
const escaped = opts.search.replace(/'/g, "''");
|
|
76
|
+
conditions.push(`(operation LIKE '%${escaped}%' OR context LIKE '%${escaped}%')`);
|
|
77
|
+
}
|
|
78
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
79
|
+
return Effect.all([
|
|
80
|
+
sql.unsafe(`SELECT * FROM audit_log ${where} ORDER BY id DESC LIMIT ${limit} OFFSET ${offset}`).pipe(Effect.map((rows) => rows.map((r) => r))),
|
|
81
|
+
sql.unsafe(`SELECT count(*) as count FROM audit_log ${where}`).pipe(Effect.map((rows) => rows[0]?.count ?? 0))
|
|
82
|
+
]).pipe(Effect.map(([items, total]) => ({
|
|
83
|
+
items,
|
|
84
|
+
total,
|
|
85
|
+
...(items.length === limit ? { nextCursor: offset + limit } : {})
|
|
86
|
+
})), cacheError("findAll"));
|
|
87
|
+
}
|
|
88
|
+
return Effect.all([
|
|
89
|
+
findAll_({ limit, offset }),
|
|
90
|
+
countAll(undefined)
|
|
91
|
+
]).pipe(Effect.map(([items, { count }]) => ({
|
|
92
|
+
items,
|
|
93
|
+
total: count,
|
|
94
|
+
...(items.length === limit ? { nextCursor: offset + limit } : {})
|
|
95
|
+
})), cacheError("findAll"));
|
|
96
|
+
},
|
|
97
|
+
prune: (retentionDays) => {
|
|
98
|
+
const days = Math.max(1, Math.floor(retentionDays));
|
|
99
|
+
return sql.unsafe(`DELETE FROM audit_log WHERE timestamp < datetime('now', '-${days} days')`).pipe(
|
|
100
|
+
// DELETE returns no rows — use changes() to get actual deleted count
|
|
101
|
+
Effect.flatMap(() => sql `SELECT changes() as n`), Effect.map((rows) => rows[0]?.n ?? 0), cacheError("prune"));
|
|
102
|
+
},
|
|
103
|
+
exportAll: (opts) => {
|
|
104
|
+
if (opts?.from && opts?.to) {
|
|
105
|
+
return sql.unsafe(`SELECT * FROM audit_log WHERE timestamp >= '${opts.from.replace(/'/g, "''")}' AND timestamp <= '${opts.to.replace(/'/g, "''")}' ORDER BY id DESC`).pipe(Effect.map((rows) => rows.map((r) => r)), cacheError("exportAll"));
|
|
106
|
+
}
|
|
107
|
+
return sql.unsafe("SELECT * FROM audit_log ORDER BY id DESC").pipe(Effect.map((rows) => rows.map((r) => r)), cacheError("exportAll"));
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
})
|
|
111
|
+
}) {
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=AuditLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditLog.js","sourceRoot":"","sources":["../../src/PermissionService/AuditLog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title PermissionGate — abstract "ask the user" interface
|
|
3
|
+
*
|
|
4
|
+
* Context.Tag (not Effect.Service) so different environments can
|
|
5
|
+
* provide different implementations:
|
|
6
|
+
* - Web: Deferred + SSE push (PermissionGateLive.ts)
|
|
7
|
+
* - TUI: stdin prompt (future)
|
|
8
|
+
* - Test: auto-allow Layer
|
|
9
|
+
*
|
|
10
|
+
* Only exposes `request` — the caller's view. The concrete implementation
|
|
11
|
+
* (PermissionGateLive) adds `resolve` and `getFirstPending` for the
|
|
12
|
+
* HTTP handler and SSE builder.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import type { Effect } from "effect";
|
|
17
|
+
import { Context, Schema } from "effect";
|
|
18
|
+
import type { PermissionDeniedError } from "../Errors.js";
|
|
19
|
+
declare const PermissionPrompt_base: Schema.Class<PermissionPrompt, {
|
|
20
|
+
id: typeof Schema.String;
|
|
21
|
+
operation: typeof Schema.String;
|
|
22
|
+
category: Schema.Literal<["read", "write"]>;
|
|
23
|
+
context: typeof Schema.String;
|
|
24
|
+
}, Schema.Struct.Encoded<{
|
|
25
|
+
id: typeof Schema.String;
|
|
26
|
+
operation: typeof Schema.String;
|
|
27
|
+
category: Schema.Literal<["read", "write"]>;
|
|
28
|
+
context: typeof Schema.String;
|
|
29
|
+
}>, never, {
|
|
30
|
+
readonly id: string;
|
|
31
|
+
} & {
|
|
32
|
+
readonly operation: string;
|
|
33
|
+
} & {
|
|
34
|
+
readonly context: string;
|
|
35
|
+
} & {
|
|
36
|
+
readonly category: "read" | "write";
|
|
37
|
+
}, {}, {}>;
|
|
38
|
+
export declare class PermissionPrompt extends PermissionPrompt_base {
|
|
39
|
+
}
|
|
40
|
+
export type PermissionResponse = "allow_once" | "always_allow" | "deny";
|
|
41
|
+
declare const PermissionGate_base: Context.TagClass<PermissionGate, "@knpkv/codecommit-core/PermissionGate", {
|
|
42
|
+
readonly request: (prompt: PermissionPrompt) => Effect.Effect<PermissionResponse, PermissionDeniedError>;
|
|
43
|
+
}>;
|
|
44
|
+
export declare class PermissionGate extends PermissionGate_base {
|
|
45
|
+
}
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=PermissionGate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionGate.d.ts","sourceRoot":"","sources":["../../src/PermissionService/PermissionGate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;;;;;;;;;;;;;;;;;;;;AAGzD,qBAAa,gBAAiB,SAAQ,qBAKpC;CAAG;AAEL,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,cAAc,GAAG,MAAM,CAAA;;sBAOjD,CAAC,MAAM,EAAE,gBAAgB,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;;AAH5G,qBAAa,cAAe,SAAQ,mBAKjC;CAAG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Context, Schema } from "effect";
|
|
2
|
+
// UUID correlates the SSE prompt → client modal → POST response
|
|
3
|
+
export class PermissionPrompt extends Schema.Class("PermissionPrompt")({
|
|
4
|
+
id: Schema.String,
|
|
5
|
+
operation: Schema.String,
|
|
6
|
+
category: Schema.Literal("read", "write"),
|
|
7
|
+
context: Schema.String
|
|
8
|
+
}) {
|
|
9
|
+
}
|
|
10
|
+
// Blocks the calling fiber until user responds or 30s timeout.
|
|
11
|
+
// Returns the response, or fails with PermissionDeniedError.
|
|
12
|
+
export class PermissionGate extends Context.Tag("@knpkv/codecommit-core/PermissionGate")() {
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=PermissionGate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionGate.js","sourceRoot":"","sources":["../../src/PermissionService/PermissionGate.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAGxC,gEAAgE;AAChE,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC,KAAK,CAAmB,kBAAkB,CAAC,CAAC;IACvF,EAAE,EAAE,MAAM,CAAC,MAAM;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM;IACxB,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC;CAAG;AAIL,+DAA+D;AAC/D,6DAA6D;AAC7D,MAAM,OAAO,cAAe,SAAQ,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,EAKrF;CAAG"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title PermissionGateLive — Deferred-based prompt flow
|
|
3
|
+
*
|
|
4
|
+
* One `Deferred<PermissionResponse>` per prompt.
|
|
5
|
+
*
|
|
6
|
+
* Flow:
|
|
7
|
+
* 1. API call fiber creates Deferred, stores in pending Map
|
|
8
|
+
* 2. Publishes PermissionRequired → SSE rebuilds payload with prompt
|
|
9
|
+
* 3. Fiber blocks on Deferred.await (up to 30s)
|
|
10
|
+
* 4. User clicks modal → POST /api/permissions/respond
|
|
11
|
+
* 5. HTTP handler calls resolve() → Deferred.succeed → fiber unblocks
|
|
12
|
+
* 6. Publishes PermissionResolved → SSE removes prompt from payload
|
|
13
|
+
*
|
|
14
|
+
* Multi-tab: Deferred.succeed is idempotent — first responder wins,
|
|
15
|
+
* second tab's POST is a no-op. Both see prompt disappear via SSE.
|
|
16
|
+
*
|
|
17
|
+
* Separate Effect.Service tag (not just PermissionGate) because the
|
|
18
|
+
* HTTP handler and SSE builder need `resolve` and `getFirstPending`
|
|
19
|
+
* which the abstract interface doesn't expose.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import { Effect, Layer } from "effect";
|
|
24
|
+
import { EventsHub } from "../CacheService/EventsHub.js";
|
|
25
|
+
import { PermissionDeniedError } from "../Errors.js";
|
|
26
|
+
import { PermissionGate, type PermissionPrompt, type PermissionResponse } from "./PermissionGate.js";
|
|
27
|
+
export interface PermissionGateLive {
|
|
28
|
+
readonly request: (prompt: PermissionPrompt) => Effect.Effect<PermissionResponse, PermissionDeniedError>;
|
|
29
|
+
readonly resolve: (promptId: string, response: PermissionResponse) => Effect.Effect<void>;
|
|
30
|
+
readonly getFirstPending: () => Effect.Effect<PermissionPrompt | undefined>;
|
|
31
|
+
}
|
|
32
|
+
export declare const PermissionGateLiveTag: Effect.Service.Class<PermissionGateLive, "PermissionGateLive", {
|
|
33
|
+
readonly dependencies: readonly [Layer.Layer<EventsHub, never, never>];
|
|
34
|
+
readonly effect: Effect.Effect<{
|
|
35
|
+
request: (prompt: PermissionPrompt) => Effect.Effect<PermissionResponse, PermissionDeniedError>;
|
|
36
|
+
resolve: (promptId: string, response: PermissionResponse) => Effect.Effect<void>;
|
|
37
|
+
getFirstPending: () => Effect.Effect<PermissionPrompt | undefined>;
|
|
38
|
+
}, never, EventsHub>;
|
|
39
|
+
}>;
|
|
40
|
+
export declare const PermissionGateLiveLayer: Layer.Layer<PermissionGate, never, PermissionGateLive>;
|
|
41
|
+
//# sourceMappingURL=PermissionGateLive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionGateLive.d.ts","sourceRoot":"","sources":["../../src/PermissionService/PermissionGateLive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAY,MAAM,EAAE,KAAK,EAAO,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,SAAS,EAAc,MAAM,8BAA8B,CAAA;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAOpG,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAA;IACxG,QAAQ,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACzF,QAAQ,CAAC,eAAe,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAAA;CAC5E;AAED,eAAO,MAAM,qBAAqB;;;0BAWL,gBAAgB,KAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC;4BAqCzE,MAAM,YAAY,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;+BAUzD,MAAM,CAAC,MAAM,CAAC,gBAAgB,GAAG,SAAS,CAAC;;EAUzE,CAAA;AAKF,eAAO,MAAM,uBAAuB,wDAGnC,CAAA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title PermissionGateLive — Deferred-based prompt flow
|
|
3
|
+
*
|
|
4
|
+
* One `Deferred<PermissionResponse>` per prompt.
|
|
5
|
+
*
|
|
6
|
+
* Flow:
|
|
7
|
+
* 1. API call fiber creates Deferred, stores in pending Map
|
|
8
|
+
* 2. Publishes PermissionRequired → SSE rebuilds payload with prompt
|
|
9
|
+
* 3. Fiber blocks on Deferred.await (up to 30s)
|
|
10
|
+
* 4. User clicks modal → POST /api/permissions/respond
|
|
11
|
+
* 5. HTTP handler calls resolve() → Deferred.succeed → fiber unblocks
|
|
12
|
+
* 6. Publishes PermissionResolved → SSE removes prompt from payload
|
|
13
|
+
*
|
|
14
|
+
* Multi-tab: Deferred.succeed is idempotent — first responder wins,
|
|
15
|
+
* second tab's POST is a no-op. Both see prompt disappear via SSE.
|
|
16
|
+
*
|
|
17
|
+
* Separate Effect.Service tag (not just PermissionGate) because the
|
|
18
|
+
* HTTP handler and SSE builder need `resolve` and `getFirstPending`
|
|
19
|
+
* which the abstract interface doesn't expose.
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import { Deferred, Effect, Layer, Ref } from "effect";
|
|
24
|
+
import { EventsHub, RepoChange } from "../CacheService/EventsHub.js";
|
|
25
|
+
import { PermissionDeniedError } from "../Errors.js";
|
|
26
|
+
import { PermissionGate } from "./PermissionGate.js";
|
|
27
|
+
export const PermissionGateLiveTag = Effect.Service()("PermissionGateLive", {
|
|
28
|
+
// EventsHub needed to publish PermissionRequired/Resolved events
|
|
29
|
+
// that trigger SSE payload rebuilds
|
|
30
|
+
dependencies: [EventsHub.Default],
|
|
31
|
+
effect: Effect.gen(function* () {
|
|
32
|
+
const hub = yield* EventsHub;
|
|
33
|
+
// Map<promptId, { deferred, prompt }>. Concurrent-safe via Ref.
|
|
34
|
+
// Multiple prompts can be pending simultaneously (e.g. initial
|
|
35
|
+
// refresh triggers getCallerIdentity + listRepositories at once).
|
|
36
|
+
const pending = yield* Ref.make(new Map());
|
|
37
|
+
const request = (prompt) => Effect.gen(function* () {
|
|
38
|
+
const deferred = yield* Deferred.make();
|
|
39
|
+
yield* Ref.update(pending, (m) => new Map(m).set(prompt.id, { deferred, prompt }));
|
|
40
|
+
yield* hub.publish(RepoChange.PermissionRequired());
|
|
41
|
+
const response = yield* Deferred.await(deferred).pipe(Effect.timeout("30 seconds"), Effect.catchTag("TimeoutException", () => {
|
|
42
|
+
return Effect.gen(function* () {
|
|
43
|
+
yield* Ref.update(pending, (m) => {
|
|
44
|
+
const n = new Map(m);
|
|
45
|
+
n.delete(prompt.id);
|
|
46
|
+
return n;
|
|
47
|
+
});
|
|
48
|
+
yield* hub.publish(RepoChange.PermissionResolved());
|
|
49
|
+
return yield* new PermissionDeniedError({ operation: prompt.operation, reason: "timeout" });
|
|
50
|
+
});
|
|
51
|
+
}));
|
|
52
|
+
yield* Ref.update(pending, (m) => {
|
|
53
|
+
const n = new Map(m);
|
|
54
|
+
n.delete(prompt.id);
|
|
55
|
+
return n;
|
|
56
|
+
});
|
|
57
|
+
yield* hub.publish(RepoChange.PermissionResolved());
|
|
58
|
+
if (response === "deny") {
|
|
59
|
+
return yield* new PermissionDeniedError({ operation: prompt.operation, reason: "denied" });
|
|
60
|
+
}
|
|
61
|
+
return response;
|
|
62
|
+
});
|
|
63
|
+
// Called by POST /api/permissions/respond handler.
|
|
64
|
+
// Deferred.succeed is idempotent — second call is a no-op.
|
|
65
|
+
// This is how multi-tab "first responder wins" works.
|
|
66
|
+
const resolve = (promptId, response) => Ref.get(pending).pipe(Effect.flatMap((m) => {
|
|
67
|
+
const entry = m.get(promptId);
|
|
68
|
+
return entry ? Deferred.succeed(entry.deferred, response) : Effect.void;
|
|
69
|
+
}));
|
|
70
|
+
// For SSE payload builder — shows one prompt at a time (FIFO).
|
|
71
|
+
// Remaining prompts queue behind; they'll surface as each resolves.
|
|
72
|
+
const getFirstPending = () => Ref.get(pending).pipe(Effect.map((m) => {
|
|
73
|
+
const first = m.values().next();
|
|
74
|
+
return first.done ? undefined : first.value.prompt;
|
|
75
|
+
}));
|
|
76
|
+
return { request, resolve, getFirstPending };
|
|
77
|
+
})
|
|
78
|
+
});
|
|
79
|
+
// Bridge: concrete service → abstract Context.Tag.
|
|
80
|
+
// Handlers use PermissionGateLiveTag (for resolve/getFirstPending),
|
|
81
|
+
// AwsClientGated uses PermissionGate (for request only).
|
|
82
|
+
export const PermissionGateLiveLayer = Layer.effect(PermissionGate, Effect.map(PermissionGateLiveTag, (live) => ({ request: live.request })));
|
|
83
|
+
//# sourceMappingURL=PermissionGateLive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PermissionGateLive.js","sourceRoot":"","sources":["../../src/PermissionService/PermissionGateLive.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title PermissionService — permission state management
|
|
3
|
+
*
|
|
4
|
+
* Ref<Config> backed by `~/.codecommit/permissions.json`.
|
|
5
|
+
*
|
|
6
|
+
* On construction (Layer build time), reads the file
|
|
7
|
+
* into a Ref. All subsequent `check()` calls are O(1) Ref lookups — no disk
|
|
8
|
+
* I/O. Only `set()` mutates the Ref AND writes to disk (atomic: tmp → rename).
|
|
9
|
+
*
|
|
10
|
+
* Key invariant: an operation missing from the file defaults to `"allow"`,
|
|
11
|
+
* which means "prompt the user". A fresh install with empty permissions.json
|
|
12
|
+
* prompts for every API call — zero-trust by default.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import { FileSystem } from "@effect/platform";
|
|
17
|
+
import { Effect, Schema } from "effect";
|
|
18
|
+
import { allOperations, getOperationMeta, type OperationName, registerOperation } from "./operations.js";
|
|
19
|
+
export type { BuiltinOperation, OperationMeta, OperationName } from "./operations.js";
|
|
20
|
+
export { allOperations, getOperationMeta, registerOperation };
|
|
21
|
+
export declare const PermissionState: Schema.Literal<["always_allow", "allow", "deny"]>;
|
|
22
|
+
export type PermissionState = typeof PermissionState.Type;
|
|
23
|
+
declare const PermissionService_base: Effect.Service.Class<PermissionService, "PermissionService", {
|
|
24
|
+
readonly effect: Effect.Effect<{
|
|
25
|
+
check: (operation: OperationName) => Effect.Effect<PermissionState>;
|
|
26
|
+
set: (operation: OperationName, state: PermissionState) => Effect.Effect<void>;
|
|
27
|
+
getAll: () => Effect.Effect<Record<string, PermissionState>>;
|
|
28
|
+
resetAll: () => Effect.Effect<void>;
|
|
29
|
+
isAuditEnabled: () => Effect.Effect<boolean>;
|
|
30
|
+
getAuditRetention: () => Effect.Effect<number>;
|
|
31
|
+
setAudit: (opts: {
|
|
32
|
+
enabled?: boolean | undefined;
|
|
33
|
+
retentionDays?: number | undefined;
|
|
34
|
+
}) => Effect.Effect<void>;
|
|
35
|
+
}, never, FileSystem.FileSystem>;
|
|
36
|
+
}>;
|
|
37
|
+
export declare class PermissionService extends PermissionService_base {
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/PermissionService/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAU,MAAM,EAAO,MAAM,EAAE,MAAM,QAAQ,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExG,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAA;AAK7D,eAAO,MAAM,eAAe,mDAAkD,CAAA;AAC9E,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;;;2BA6D3B,aAAa,KAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;yBAGhD,aAAa,SAAS,eAAe,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;sBAShE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;wBAG5C,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;8BAMb,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;iCAEnB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;yBAI3C;YAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;SAAE,KAC1E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;;;AAzC1B,qBAAa,iBAAkB,SAAQ,sBAuDrC;CAAG"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title PermissionService — permission state management
|
|
3
|
+
*
|
|
4
|
+
* Ref<Config> backed by `~/.codecommit/permissions.json`.
|
|
5
|
+
*
|
|
6
|
+
* On construction (Layer build time), reads the file
|
|
7
|
+
* into a Ref. All subsequent `check()` calls are O(1) Ref lookups — no disk
|
|
8
|
+
* I/O. Only `set()` mutates the Ref AND writes to disk (atomic: tmp → rename).
|
|
9
|
+
*
|
|
10
|
+
* Key invariant: an operation missing from the file defaults to `"allow"`,
|
|
11
|
+
* which means "prompt the user". A fresh install with empty permissions.json
|
|
12
|
+
* prompts for every API call — zero-trust by default.
|
|
13
|
+
*
|
|
14
|
+
* @module
|
|
15
|
+
*/
|
|
16
|
+
import { FileSystem } from "@effect/platform";
|
|
17
|
+
import { Config, Effect, Ref, Schema } from "effect";
|
|
18
|
+
import { allOperations, getOperationMeta, registerOperation } from "./operations.js";
|
|
19
|
+
export { allOperations, getOperationMeta, registerOperation };
|
|
20
|
+
// On-disk format. Schema.decodeUnknownSync with defaults means
|
|
21
|
+
// corrupt or missing files gracefully degrade to empty state (everything prompts).
|
|
22
|
+
export const PermissionState = Schema.Literal("always_allow", "allow", "deny");
|
|
23
|
+
const AuditConfig = Schema.Struct({
|
|
24
|
+
enabled: Schema.Boolean.pipe(Schema.optionalWith({ default: () => true })),
|
|
25
|
+
retentionDays: Schema.Number.pipe(Schema.optionalWith({ default: () => 30 }))
|
|
26
|
+
});
|
|
27
|
+
const PermissionsConfig = Schema.Struct({
|
|
28
|
+
permissions: Schema.Record({ key: Schema.String, value: PermissionState }).pipe(Schema.optionalWith({ default: () => ({}) })),
|
|
29
|
+
audit: AuditConfig.pipe(Schema.optionalWith({ default: () => Schema.decodeSync(AuditConfig)({}) }))
|
|
30
|
+
});
|
|
31
|
+
const decodeConfig = Schema.decodeUnknownSync(PermissionsConfig);
|
|
32
|
+
// Uses @effect/platform FileSystem — works in Bun, Node, tests.
|
|
33
|
+
// Atomic write: write to .tmp, then rename. Prevents corruption on crash.
|
|
34
|
+
const resolvePermissionsPath = Config.string("HOME").pipe(Config.orElse(() => Config.string("USERPROFILE")), Config.map((h) => `${h}/.codecommit/permissions.json`));
|
|
35
|
+
const loadFromDisk = (fs, path) => fs.readFileString(path).pipe(Effect.map((content) => decodeConfig(JSON.parse(content))),
|
|
36
|
+
// Any failure → empty config → everything prompts
|
|
37
|
+
Effect.catchAll(() => Effect.succeed(decodeConfig({}))));
|
|
38
|
+
const saveToDisk = (fs, path, config) => Effect.gen(function* () {
|
|
39
|
+
const dir = path.replace(/\/[^/]+$/, "");
|
|
40
|
+
yield* fs.makeDirectory(dir, { recursive: true }).pipe(Effect.catchAll(() => Effect.void));
|
|
41
|
+
const tmpPath = `${path}.tmp`;
|
|
42
|
+
yield* fs.writeFileString(tmpPath, JSON.stringify(config, null, 2));
|
|
43
|
+
yield* fs.rename(tmpPath, path);
|
|
44
|
+
}).pipe(Effect.catchAll(() => Effect.void));
|
|
45
|
+
// Effect.Service (not Context.Tag) — auto-generates `.Default` layer.
|
|
46
|
+
// The effect block runs once at Layer construction: reads file, creates Ref.
|
|
47
|
+
// FileSystem comes from the providing layer (PlatformLive in Server.ts).
|
|
48
|
+
export class PermissionService extends Effect.Service()("PermissionService", {
|
|
49
|
+
effect: Effect.gen(function* () {
|
|
50
|
+
const fs = yield* FileSystem.FileSystem;
|
|
51
|
+
const permPath = yield* Effect.configProviderWith((p) => p.load(resolvePermissionsPath)).pipe(Effect.catchAll(() => Effect.succeed("/tmp/.codecommit/permissions.json")));
|
|
52
|
+
// In-memory state. All check() calls read from here.
|
|
53
|
+
// Only set() mutates it AND writes to disk.
|
|
54
|
+
const initial = yield* loadFromDisk(fs, permPath);
|
|
55
|
+
const configRef = yield* Ref.make(initial);
|
|
56
|
+
// O(1) — Ref.get + property lookup. The "allow" default is the key invariant:
|
|
57
|
+
// missing operation → prompt the user.
|
|
58
|
+
const check = (operation) => Ref.get(configRef).pipe(Effect.map((c) => c.permissions[operation] ?? "allow"));
|
|
59
|
+
const set = (operation, state) => Effect.gen(function* () {
|
|
60
|
+
yield* Ref.update(configRef, (c) => ({
|
|
61
|
+
...c,
|
|
62
|
+
permissions: { ...c.permissions, [operation]: state }
|
|
63
|
+
}));
|
|
64
|
+
yield* saveToDisk(fs, permPath, yield* Ref.get(configRef));
|
|
65
|
+
});
|
|
66
|
+
const getAll = () => Ref.get(configRef).pipe(Effect.map((c) => c.permissions));
|
|
67
|
+
const resetAll = () => Effect.gen(function* () {
|
|
68
|
+
yield* Ref.update(configRef, (c) => ({ ...c, permissions: {} }));
|
|
69
|
+
yield* saveToDisk(fs, permPath, yield* Ref.get(configRef));
|
|
70
|
+
});
|
|
71
|
+
const isAuditEnabled = () => Ref.get(configRef).pipe(Effect.map((c) => c.audit.enabled));
|
|
72
|
+
const getAuditRetention = () => Ref.get(configRef).pipe(Effect.map((c) => c.audit.retentionDays));
|
|
73
|
+
const setAudit = (opts) => Effect.gen(function* () {
|
|
74
|
+
yield* Ref.update(configRef, (c) => ({
|
|
75
|
+
...c,
|
|
76
|
+
audit: {
|
|
77
|
+
enabled: opts.enabled ?? c.audit.enabled,
|
|
78
|
+
retentionDays: opts.retentionDays ?? c.audit.retentionDays
|
|
79
|
+
}
|
|
80
|
+
}));
|
|
81
|
+
yield* saveToDisk(fs, permPath, yield* Ref.get(configRef));
|
|
82
|
+
});
|
|
83
|
+
return { check, set, getAll, resetAll, isAuditEnabled, getAuditRetention, setAudit };
|
|
84
|
+
})
|
|
85
|
+
}) {
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/PermissionService/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Operation registry — maps operation names to metadata
|
|
3
|
+
*
|
|
4
|
+
* Every AWS API call has a named operation with a category (read/write)
|
|
5
|
+
* and human-readable description. The gate uses the category for UI
|
|
6
|
+
* badge color; the description appears in the permission prompt modal.
|
|
7
|
+
*
|
|
8
|
+
* `OperationName` is a union of known builtin operations + `(string & {})`
|
|
9
|
+
* for runtime extensions. This gives autocomplete for known ops while
|
|
10
|
+
* allowing `registerOperation` to add new ones (e.g. approval rule CRUD).
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export interface OperationMeta {
|
|
15
|
+
readonly category: "read" | "write";
|
|
16
|
+
readonly description: string;
|
|
17
|
+
}
|
|
18
|
+
declare const BuiltinOperations: {
|
|
19
|
+
readonly getCallerIdentity: OperationMeta;
|
|
20
|
+
readonly listRepositories: OperationMeta;
|
|
21
|
+
readonly listPullRequests: OperationMeta;
|
|
22
|
+
readonly getPullRequests: OperationMeta;
|
|
23
|
+
readonly getPullRequest: OperationMeta;
|
|
24
|
+
readonly evaluatePullRequestApprovalRules: OperationMeta;
|
|
25
|
+
readonly getPullRequestApprovalStates: OperationMeta;
|
|
26
|
+
readonly getMergeConflicts: OperationMeta;
|
|
27
|
+
readonly getCommentsForPullRequest: OperationMeta;
|
|
28
|
+
readonly listBranches: OperationMeta;
|
|
29
|
+
readonly getDifferences: OperationMeta;
|
|
30
|
+
readonly createPullRequest: OperationMeta;
|
|
31
|
+
readonly updatePullRequestTitle: OperationMeta;
|
|
32
|
+
readonly updatePullRequestDescription: OperationMeta;
|
|
33
|
+
};
|
|
34
|
+
export type BuiltinOperation = keyof typeof BuiltinOperations;
|
|
35
|
+
export type OperationName = BuiltinOperation | (string & {});
|
|
36
|
+
export declare const getOperationMeta: (name: OperationName) => OperationMeta;
|
|
37
|
+
export declare const allOperations: () => ReadonlyArray<readonly [string, OperationMeta]>;
|
|
38
|
+
export declare const registerOperation: (name: string, meta: OperationMeta) => void;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=operations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/PermissionService/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAID,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;CAe2B,CAAA;AAElD,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,iBAAiB,CAAA;AAG7D,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAM5D,eAAO,MAAM,gBAAgB,GAAI,MAAM,aAAa,KAAG,aAAuD,CAAA;AAE9G,eAAO,MAAM,aAAa,QAAO,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAA8B,CAAA;AAE7G,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,EAAE,MAAM,aAAa,KAAG,IAErE,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @title Operation registry — maps operation names to metadata
|
|
3
|
+
*
|
|
4
|
+
* Every AWS API call has a named operation with a category (read/write)
|
|
5
|
+
* and human-readable description. The gate uses the category for UI
|
|
6
|
+
* badge color; the description appears in the permission prompt modal.
|
|
7
|
+
*
|
|
8
|
+
* `OperationName` is a union of known builtin operations + `(string & {})`
|
|
9
|
+
* for runtime extensions. This gives autocomplete for known ops while
|
|
10
|
+
* allowing `registerOperation` to add new ones (e.g. approval rule CRUD).
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
const op = (category, description) => ({ category, description });
|
|
15
|
+
const BuiltinOperations = {
|
|
16
|
+
getCallerIdentity: op("read", "Get current user identity"),
|
|
17
|
+
listRepositories: op("read", "List all repositories"),
|
|
18
|
+
listPullRequests: op("read", "List PR IDs for a repo"),
|
|
19
|
+
getPullRequests: op("read", "Fetch PR details"),
|
|
20
|
+
getPullRequest: op("read", "Single PR detail"),
|
|
21
|
+
evaluatePullRequestApprovalRules: op("read", "Check approval status"),
|
|
22
|
+
getPullRequestApprovalStates: op("read", "Get who approved"),
|
|
23
|
+
getMergeConflicts: op("read", "Check merge conflicts"),
|
|
24
|
+
getCommentsForPullRequest: op("read", "Fetch PR comments"),
|
|
25
|
+
listBranches: op("read", "List branches"),
|
|
26
|
+
getDifferences: op("read", "Diff stats"),
|
|
27
|
+
createPullRequest: op("write", "Create a pull request"),
|
|
28
|
+
updatePullRequestTitle: op("write", "Edit PR title"),
|
|
29
|
+
updatePullRequestDescription: op("write", "Edit PR description")
|
|
30
|
+
};
|
|
31
|
+
const operations = new Map(Object.entries(BuiltinOperations));
|
|
32
|
+
const fallback = (name) => ({ category: "read", description: name });
|
|
33
|
+
export const getOperationMeta = (name) => operations.get(name) ?? fallback(name);
|
|
34
|
+
export const allOperations = () => [...operations.entries()];
|
|
35
|
+
export const registerOperation = (name, meta) => {
|
|
36
|
+
operations.set(name, meta);
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/PermissionService/operations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,EAAE,GAAG,CAAC,QAA0B,EAAE,WAAmB,EAAiB,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAA;AAE1G,MAAM,iBAAiB,GAAG;IACxB,iBAAiB,EAAE,EAAE,CAAC,MAAM,EAAE,2BAA2B,CAAC;IAC1D,gBAAgB,EAAE,EAAE,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACrD,gBAAgB,EAAE,EAAE,CAAC,MAAM,EAAE,wBAAwB,CAAC;IACtD,eAAe,EAAE,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAC/C,cAAc,EAAE,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAC9C,gCAAgC,EAAE,EAAE,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACrE,4BAA4B,EAAE,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAC5D,iBAAiB,EAAE,EAAE,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACtD,yBAAyB,EAAE,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC;IAC1D,YAAY,EAAE,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC;IACzC,cAAc,EAAE,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;IACxC,iBAAiB,EAAE,EAAE,CAAC,OAAO,EAAE,uBAAuB,CAAC;IACvD,sBAAsB,EAAE,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC;IACpD,4BAA4B,EAAE,EAAE,CAAC,OAAO,EAAE,qBAAqB,CAAC;CAChB,CAAA;AAOlD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAwB,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAEpF,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAiB,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;AAE3F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAmB,EAAiB,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAA;AAE9G,MAAM,CAAC,MAAM,aAAa,GAAG,GAAoD,EAAE,CAAC,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,CAAA;AAE7G,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAE,IAAmB,EAAQ,EAAE;IAC3E,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAC5B,CAAC,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export * as ConfigService from "./ConfigService/index.js";
|
|
|
20
20
|
export * as DateUtils from "./DateUtils.js";
|
|
21
21
|
export * as Domain from "./Domain.js";
|
|
22
22
|
export * as Errors from "./Errors.js";
|
|
23
|
+
export * as PermissionService from "./PermissionService/index.js";
|
|
23
24
|
export * as PRService from "./PRService/index.js";
|
|
24
25
|
export * as SandboxService from "./SandboxService/index.js";
|
|
25
26
|
export * as StatsService from "./StatsService/index.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AAGvD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,iBAAiB,MAAM,8BAA8B,CAAA;AACjE,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AAGvD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ export * as ConfigService from "./ConfigService/index.js";
|
|
|
20
20
|
export * as DateUtils from "./DateUtils.js";
|
|
21
21
|
export * as Domain from "./Domain.js";
|
|
22
22
|
export * as Errors from "./Errors.js";
|
|
23
|
+
export * as PermissionService from "./PermissionService/index.js";
|
|
23
24
|
export * as PRService from "./PRService/index.js";
|
|
24
25
|
export * as SandboxService from "./SandboxService/index.js";
|
|
25
26
|
export * as StatsService from "./StatsService/index.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AAEvD,gDAAgD;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AACvD,OAAO,KAAK,aAAa,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAA;AAC3C,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,iBAAiB,MAAM,8BAA8B,CAAA;AACjE,OAAO,KAAK,SAAS,MAAM,sBAAsB,CAAA;AACjD,OAAO,KAAK,cAAc,MAAM,2BAA2B,CAAA;AAC3D,OAAO,KAAK,YAAY,MAAM,yBAAyB,CAAA;AAEvD,gDAAgD;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|