@ya-accelerators/web-backend-framework 0.0.66 → 0.0.68
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/corporate-service-auth/index.d.ts +4 -0
- package/dist/corporate-service-auth/index.js +95 -0
- package/dist/corporate-service-auth/index.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.js +14 -6
- package/dist/env.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/s3/index.js +6 -5
- package/dist/s3/index.js.map +1 -1
- package/dist/worker/index.d.ts +86 -0
- package/dist/worker/index.js +98 -0
- package/dist/worker/index.js.map +1 -0
- package/package.json +4 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { defaultEnv } from "../env.js";
|
|
2
|
+
import { logger } from "../logger/index.js";
|
|
3
|
+
import { runWithRequestHeaders } from "../request-context/index.js";
|
|
4
|
+
// Consumer-side auth for calling the central corporate-service (the Estonia-entity compliance
|
|
5
|
+
// runtime). Uses AWS → Google Workload Identity Federation: the running AWS identity federates into
|
|
6
|
+
// a Google Workload Identity Pool, impersonates the configured service account, and mints a
|
|
7
|
+
// Google-signed OIDC ID token for the configured audience. The token is cached and forwarded as a
|
|
8
|
+
// Bearer header so the thin per-env dist client reaches corporate-service authenticated. Uniform
|
|
9
|
+
// across dev/stg/prd — the same WIF config yields a real Google id_token that corporate-service
|
|
10
|
+
// verifies against Google's JWKS; only the AWS identity behind the federation differs. The config
|
|
11
|
+
// holds no credential (it points at the pool / provider / SA), so it lives in .env plaintext.
|
|
12
|
+
//
|
|
13
|
+
// The AWS identity is resolved through the AWS SDK credential chain (env / ECS container credential
|
|
14
|
+
// endpoint / EC2 IMDS, with rotation) rather than google-auth-library's built-in IMDS-only source,
|
|
15
|
+
// so federation works on ECS Fargate, where task-role credentials live at the container credential
|
|
16
|
+
// endpoint instead of IMDS.
|
|
17
|
+
const ID_TOKEN_TTL_SEC = 3600;
|
|
18
|
+
const REFRESH_SKEW_MS = 5 * 60 * 1000;
|
|
19
|
+
let cached;
|
|
20
|
+
let inflight;
|
|
21
|
+
let awsCredentialProvider;
|
|
22
|
+
const fetchIdToken = async () => {
|
|
23
|
+
if (defaultEnv.CORPORATE_SERVICE_AUDIENCE === undefined) {
|
|
24
|
+
throw new Error('corporateServiceAuth: CORPORATE_SERVICE_AUDIENCE is not set');
|
|
25
|
+
}
|
|
26
|
+
if (defaultEnv.CORPORATE_SERVICE_WIF_CONFIG_BASE64 === undefined) {
|
|
27
|
+
throw new Error('corporateServiceAuth: CORPORATE_SERVICE_WIF_CONFIG_BASE64 is not set');
|
|
28
|
+
}
|
|
29
|
+
// google-auth-library and the AWS credential provider are dynamically imported so services that
|
|
30
|
+
// never call corporate-service do not load them.
|
|
31
|
+
const { AwsClient, Impersonated } = await import('google-auth-library');
|
|
32
|
+
const { defaultProvider } = await import('@aws-sdk/credential-provider-node');
|
|
33
|
+
const credentialProvider = (awsCredentialProvider ??= defaultProvider());
|
|
34
|
+
const config = JSON.parse(Buffer.from(defaultEnv.CORPORATE_SERVICE_WIF_CONFIG_BASE64, 'base64').toString('utf8'));
|
|
35
|
+
if (config.service_account_impersonation_url === undefined) {
|
|
36
|
+
throw new Error('corporateServiceAuth: WIF config missing service_account_impersonation_url');
|
|
37
|
+
}
|
|
38
|
+
const serviceAccountEmail = config.service_account_impersonation_url.match(/serviceAccounts\/([^/:]+):/)?.[1];
|
|
39
|
+
if (serviceAccountEmail === undefined) {
|
|
40
|
+
throw new Error('corporateServiceAuth: cannot derive service account email from WIF config');
|
|
41
|
+
}
|
|
42
|
+
// Federation-only client (impersonation + the built-in IMDS source stripped); Impersonated below
|
|
43
|
+
// performs the SA impersonation via generateIdToken, for which the federated principal already
|
|
44
|
+
// holds roles/iam.serviceAccountTokenCreator on the SA.
|
|
45
|
+
return {
|
|
46
|
+
token: await new Impersonated({
|
|
47
|
+
sourceClient: new AwsClient({
|
|
48
|
+
...config,
|
|
49
|
+
service_account_impersonation_url: undefined,
|
|
50
|
+
credential_source: undefined,
|
|
51
|
+
aws_security_credentials_supplier: {
|
|
52
|
+
getAwsRegion: async () => {
|
|
53
|
+
if (defaultEnv.AWS_REGION === undefined) {
|
|
54
|
+
throw new Error('corporateServiceAuth: AWS_REGION is not set');
|
|
55
|
+
}
|
|
56
|
+
return defaultEnv.AWS_REGION;
|
|
57
|
+
},
|
|
58
|
+
getAwsSecurityCredentials: async () => {
|
|
59
|
+
const c = await credentialProvider();
|
|
60
|
+
return { accessKeyId: c.accessKeyId, secretAccessKey: c.secretAccessKey, token: c.sessionToken };
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
targetPrincipal: serviceAccountEmail,
|
|
65
|
+
lifetime: ID_TOKEN_TTL_SEC,
|
|
66
|
+
targetScopes: ['https://www.googleapis.com/auth/cloud-platform'],
|
|
67
|
+
})
|
|
68
|
+
.fetchIdToken(defaultEnv.CORPORATE_SERVICE_AUDIENCE, { includeEmail: true })
|
|
69
|
+
.catch((e) => {
|
|
70
|
+
logger.error('corporate-service-auth', { error: e });
|
|
71
|
+
throw e;
|
|
72
|
+
}),
|
|
73
|
+
// Google id_tokens are valid for ID_TOKEN_TTL_SEC; bearer() refreshes REFRESH_SKEW_MS earlier. Computed
|
|
74
|
+
// after the mint await, so the expiry tracks the token's real `exp` (the sub-second offset is immaterial
|
|
75
|
+
// against the 5-min REFRESH_SKEW_MS).
|
|
76
|
+
expiresAt: (Math.floor(Date.now() / 1000) + ID_TOKEN_TTL_SEC) * 1000,
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
const bearer = async () => {
|
|
80
|
+
if (cached !== undefined && Date.now() <= cached.expiresAt - REFRESH_SKEW_MS) {
|
|
81
|
+
return `Bearer ${cached.token}`;
|
|
82
|
+
}
|
|
83
|
+
if (inflight === undefined) {
|
|
84
|
+
inflight = fetchIdToken().finally(() => {
|
|
85
|
+
inflight = undefined;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
cached = await inflight;
|
|
89
|
+
return `Bearer ${cached.token}`;
|
|
90
|
+
};
|
|
91
|
+
export const corporateServiceAuth = {
|
|
92
|
+
bearer,
|
|
93
|
+
withAuth: async (fn) => runWithRequestHeaders({ authorization: await bearer() }, fn),
|
|
94
|
+
};
|
|
95
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/corporate-service-auth/index.ts"],"names":[],"mappings":"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"}
|
package/dist/env.d.ts
CHANGED
|
@@ -17,4 +17,6 @@ export declare const defaultEnv: {
|
|
|
17
17
|
DATABASE_NAME?: string | undefined;
|
|
18
18
|
LOCAL_S3_ENDPOINT?: string | undefined;
|
|
19
19
|
AWS_REGION?: string | undefined;
|
|
20
|
+
CORPORATE_SERVICE_AUDIENCE?: string | undefined;
|
|
21
|
+
CORPORATE_SERVICE_WIF_CONFIG_BASE64?: string | undefined;
|
|
20
22
|
};
|
package/dist/env.js
CHANGED
|
@@ -2,8 +2,8 @@ import { z } from 'zod';
|
|
|
2
2
|
import { Util } from "./util/index.js";
|
|
3
3
|
export const defaultEnv = Util.createEnvProxy(z.object({
|
|
4
4
|
// common
|
|
5
|
-
NODE_ENV: z.enum(['development', 'production'])
|
|
6
|
-
DEPLOY_ENV: z.enum(['dev', 'stg', 'prd'])
|
|
5
|
+
NODE_ENV: z.enum(['development', 'production']),
|
|
6
|
+
DEPLOY_ENV: z.enum(['dev', 'stg', 'prd']),
|
|
7
7
|
// When unset, the threshold defaults to debug on local dev and info on stg/prd (see logger).
|
|
8
8
|
LOG_LEVEL: z.enum(['debug', 'info', 'warn', 'error']).optional(),
|
|
9
9
|
// general
|
|
@@ -14,10 +14,7 @@ export const defaultEnv = Util.createEnvProxy(z.object({
|
|
|
14
14
|
DATABASE_USER: z.string().min(1),
|
|
15
15
|
DATABASE_PASSWORD: z.string().min(1),
|
|
16
16
|
DATABASE_NAME: z.string().min(1).optional(),
|
|
17
|
-
REDIS_CLUSTER: z
|
|
18
|
-
.string()
|
|
19
|
-
.default('false')
|
|
20
|
-
.transform((val) => val === 'true'),
|
|
17
|
+
REDIS_CLUSTER: z.string().transform((val) => val === 'true'),
|
|
21
18
|
REDIS_HOST: z.string().min(1),
|
|
22
19
|
REDIS_PORT: z.string().min(1).transform(Number),
|
|
23
20
|
// package env
|
|
@@ -27,6 +24,14 @@ export const defaultEnv = Util.createEnvProxy(z.object({
|
|
|
27
24
|
// s3 (object storage) — LOCAL_S3_ENDPOINT points the client at MinIO on dev; both fall back to the AWS resolution chain
|
|
28
25
|
LOCAL_S3_ENDPOINT: z.string().optional(),
|
|
29
26
|
AWS_REGION: z.string().optional(),
|
|
27
|
+
// corporate-service consumer auth — only services that call the central corporate-service set these.
|
|
28
|
+
// CORPORATE_SERVICE_WIF_CONFIG_BASE64 is the AWS → Google Workload Identity Federation cred config
|
|
29
|
+
// (no credential inside; .env plaintext). Kept optional with no object-level refine: a non-consumer
|
|
30
|
+
// service must not fail env validation for these. corporateServiceAuth.bearer() fails-closed (throws)
|
|
31
|
+
// at call time when unset; a consumer that wants boot-time validation adds it in its own constants.ts.
|
|
32
|
+
// See corporate-service-auth.
|
|
33
|
+
CORPORATE_SERVICE_AUDIENCE: z.string().optional(),
|
|
34
|
+
CORPORATE_SERVICE_WIF_CONFIG_BASE64: z.string().optional(),
|
|
30
35
|
}), () => ({
|
|
31
36
|
// common
|
|
32
37
|
NODE_ENV: process.env.NODE_ENV,
|
|
@@ -50,5 +55,8 @@ export const defaultEnv = Util.createEnvProxy(z.object({
|
|
|
50
55
|
// s3 (object storage)
|
|
51
56
|
LOCAL_S3_ENDPOINT: process.env.LOCAL_S3_ENDPOINT,
|
|
52
57
|
AWS_REGION: process.env.AWS_REGION,
|
|
58
|
+
// corporate-service consumer auth
|
|
59
|
+
CORPORATE_SERVICE_AUDIENCE: process.env.CORPORATE_SERVICE_AUDIENCE,
|
|
60
|
+
CORPORATE_SERVICE_WIF_CONFIG_BASE64: process.env.CORPORATE_SERVICE_WIF_CONFIG_BASE64,
|
|
53
61
|
}));
|
|
54
62
|
//# sourceMappingURL=env.js.map
|
package/dist/env.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEtC,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAC3C,CAAC,CAAC,MAAM,CAAC;IACP,SAAS;IACT,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC
|
|
1
|
+
{"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './app/index.ts';
|
|
2
2
|
export * from './audit-context/index.ts';
|
|
3
|
+
export * from './corporate-service-auth/index.ts';
|
|
3
4
|
export * from './env.ts';
|
|
4
5
|
export * from './lock/index.ts';
|
|
5
6
|
export * from './logger/index.ts';
|
|
@@ -9,3 +10,4 @@ export * from './redis/index.ts';
|
|
|
9
10
|
export * from './s3/index.ts';
|
|
10
11
|
export * from './throttle/index.ts';
|
|
11
12
|
export * from './util/index.ts';
|
|
13
|
+
export * from './worker/index.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./app/index.js";
|
|
2
2
|
export * from "./audit-context/index.js";
|
|
3
|
+
export * from "./corporate-service-auth/index.js";
|
|
3
4
|
export * from "./env.js";
|
|
4
5
|
export * from "./lock/index.js";
|
|
5
6
|
export * from "./logger/index.js";
|
|
@@ -9,4 +10,5 @@ export * from "./redis/index.js";
|
|
|
9
10
|
export * from "./s3/index.js";
|
|
10
11
|
export * from "./throttle/index.js";
|
|
11
12
|
export * from "./util/index.js";
|
|
13
|
+
export * from "./worker/index.js";
|
|
12
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,0BAA0B,CAAA;AACxC,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,0BAA0B,CAAA;AACxC,cAAc,mCAAmC,CAAA;AACjD,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA"}
|
package/dist/s3/index.js
CHANGED
|
@@ -59,10 +59,11 @@ const listObjectVersions = async (params) => {
|
|
|
59
59
|
return versions;
|
|
60
60
|
};
|
|
61
61
|
// Delete versions of a key no longer referenced (`keepVersionIds` = the version-ids still indexed).
|
|
62
|
-
// A version still under retention cannot be deleted:
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
62
|
+
// A version still under retention cannot be deleted: it is returned in `skippedVersionIds` rather than
|
|
63
|
+
// failing the whole sweep. The retention denial surfaces as `AccessDenied` on AWS S3 and as
|
|
64
|
+
// `InvalidRequest` on MinIO (local/dev) — both are treated as "retained, skip". GOVERNANCE-mode
|
|
65
|
+
// versions under retention are deletable only with `governanceBypass` (requires
|
|
66
|
+
// `s3:BypassGovernanceRetention`). Any other error propagates.
|
|
66
67
|
const deleteOrphanVersions = async (params) => {
|
|
67
68
|
const keep = new Set(params.keepVersionIds);
|
|
68
69
|
const deletedVersionIds = [];
|
|
@@ -81,7 +82,7 @@ const deleteOrphanVersions = async (params) => {
|
|
|
81
82
|
deletedVersionIds.push(version.versionId);
|
|
82
83
|
}
|
|
83
84
|
catch (error) {
|
|
84
|
-
if (error instanceof Error && error.name === 'AccessDenied') {
|
|
85
|
+
if (error instanceof Error && (error.name === 'AccessDenied' || error.name === 'InvalidRequest')) {
|
|
85
86
|
skippedVersionIds.push(version.versionId);
|
|
86
87
|
}
|
|
87
88
|
else {
|
package/dist/s3/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/s3/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/s3/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
type PurgeDelegate = {
|
|
2
|
+
findMany: (args: {
|
|
3
|
+
where: Record<string, {
|
|
4
|
+
lt: Date;
|
|
5
|
+
} | {
|
|
6
|
+
gt: string;
|
|
7
|
+
}>;
|
|
8
|
+
select: {
|
|
9
|
+
id: true;
|
|
10
|
+
};
|
|
11
|
+
orderBy: {
|
|
12
|
+
id: 'asc';
|
|
13
|
+
};
|
|
14
|
+
take: number;
|
|
15
|
+
}) => Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
}[]>;
|
|
18
|
+
deleteMany: (args: {
|
|
19
|
+
where: {
|
|
20
|
+
id: {
|
|
21
|
+
in: string[];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
}) => Promise<{
|
|
25
|
+
count: number;
|
|
26
|
+
}>;
|
|
27
|
+
};
|
|
28
|
+
export type PurgeTarget = {
|
|
29
|
+
delegate: string;
|
|
30
|
+
category: string;
|
|
31
|
+
anchorField: string;
|
|
32
|
+
};
|
|
33
|
+
export declare const retentionPurge: (params: {
|
|
34
|
+
delegateFor: (name: string) => PurgeDelegate | undefined;
|
|
35
|
+
targets: readonly PurgeTarget[];
|
|
36
|
+
cutoffFor: (category: string, now: Date) => Date | null;
|
|
37
|
+
retainIds?: (delegate: string, ids: readonly string[]) => Promise<readonly string[]>;
|
|
38
|
+
now?: Date;
|
|
39
|
+
}) => Promise<void>;
|
|
40
|
+
export type EraseClient = {
|
|
41
|
+
pollErasureRequests: (input: {
|
|
42
|
+
idempotencyKey: string;
|
|
43
|
+
}) => Promise<{
|
|
44
|
+
requestId: string;
|
|
45
|
+
subjectId: string;
|
|
46
|
+
subjectType: string;
|
|
47
|
+
deferReason?: string;
|
|
48
|
+
}[]>;
|
|
49
|
+
reportErasureResult: (input: {
|
|
50
|
+
requestId: string;
|
|
51
|
+
status: 'erased' | 'skipped' | 'deferred' | 'failed';
|
|
52
|
+
anonymizedFields?: string[];
|
|
53
|
+
deferReason?: string;
|
|
54
|
+
error?: {
|
|
55
|
+
code: string;
|
|
56
|
+
message: string;
|
|
57
|
+
};
|
|
58
|
+
idempotencyKey: string;
|
|
59
|
+
}) => Promise<void>;
|
|
60
|
+
};
|
|
61
|
+
type EraseDelegate = {
|
|
62
|
+
deleteMany: (args: {
|
|
63
|
+
where: Record<string, string>;
|
|
64
|
+
}) => Promise<{
|
|
65
|
+
count: number;
|
|
66
|
+
}>;
|
|
67
|
+
updateMany: (args: {
|
|
68
|
+
where: Record<string, string>;
|
|
69
|
+
data: Record<string, null>;
|
|
70
|
+
}) => Promise<{
|
|
71
|
+
count: number;
|
|
72
|
+
}>;
|
|
73
|
+
};
|
|
74
|
+
export type EraseTarget = {
|
|
75
|
+
delegate: string;
|
|
76
|
+
subjectField: string;
|
|
77
|
+
strategy: 'delete-row' | 'anonymize';
|
|
78
|
+
piiFields: readonly string[];
|
|
79
|
+
};
|
|
80
|
+
export declare const erase: (params: {
|
|
81
|
+
client: EraseClient;
|
|
82
|
+
delegateFor: (name: string) => EraseDelegate | undefined;
|
|
83
|
+
targets: readonly EraseTarget[];
|
|
84
|
+
idempotencyKey: () => string;
|
|
85
|
+
}) => Promise<void>;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { logger } from "../logger/index.js";
|
|
2
|
+
const PURGE_BATCH = 1000;
|
|
3
|
+
export const retentionPurge = async (params) => {
|
|
4
|
+
const now = params.now ?? new Date();
|
|
5
|
+
for (const target of params.targets) {
|
|
6
|
+
const cutoff = params.cutoffFor(target.category, now);
|
|
7
|
+
if (cutoff === null) {
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
const delegate = params.delegateFor(target.delegate);
|
|
11
|
+
if (delegate === undefined) {
|
|
12
|
+
logger.error('retention-purge', { delegate: target.delegate, message: 'no matching prisma delegate' });
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
// Small idempotent id-cursor pages; a null anchor (window not started) is excluded by `lt`.
|
|
16
|
+
let afterId = '';
|
|
17
|
+
for (;;) {
|
|
18
|
+
const rows = await delegate.findMany({
|
|
19
|
+
where: { [target.anchorField]: { lt: cutoff }, id: { gt: afterId } },
|
|
20
|
+
select: { id: true },
|
|
21
|
+
orderBy: { id: 'asc' },
|
|
22
|
+
take: PURGE_BATCH,
|
|
23
|
+
});
|
|
24
|
+
if (rows.length === 0) {
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
afterId = rows[rows.length - 1].id;
|
|
28
|
+
const ids = rows.map((row) => row.id);
|
|
29
|
+
const retained = params.retainIds ? new Set(await params.retainIds(target.delegate, ids)) : undefined;
|
|
30
|
+
const toDelete = retained ? ids.filter((id) => !retained.has(id)) : ids;
|
|
31
|
+
if (toDelete.length > 0) {
|
|
32
|
+
await delegate.deleteMany({ where: { id: { in: toDelete } } });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export const erase = async (params) => {
|
|
38
|
+
const requests = await params.client.pollErasureRequests({ idempotencyKey: params.idempotencyKey() });
|
|
39
|
+
for (const request of requests) {
|
|
40
|
+
// A subject under an active legal hold is reported `deferred` and left untouched (infra.md § 11);
|
|
41
|
+
// the next cycle re-polls it and erases once the hold is released.
|
|
42
|
+
if (request.deferReason !== undefined) {
|
|
43
|
+
await params.client
|
|
44
|
+
.reportErasureResult({
|
|
45
|
+
requestId: request.requestId,
|
|
46
|
+
status: 'deferred',
|
|
47
|
+
deferReason: request.deferReason,
|
|
48
|
+
idempotencyKey: params.idempotencyKey(),
|
|
49
|
+
})
|
|
50
|
+
.catch((e) => {
|
|
51
|
+
logger.error('erase', { requestId: request.requestId, error: e });
|
|
52
|
+
});
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const anonymizedFields = [];
|
|
57
|
+
let touched = false;
|
|
58
|
+
for (const target of params.targets) {
|
|
59
|
+
const delegate = params.delegateFor(target.delegate);
|
|
60
|
+
if (delegate === undefined) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (target.strategy === 'delete-row') {
|
|
64
|
+
const { count } = await delegate.deleteMany({ where: { [target.subjectField]: request.subjectId } });
|
|
65
|
+
touched = touched || count > 0;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
const { count } = await delegate.updateMany({
|
|
69
|
+
where: { [target.subjectField]: request.subjectId },
|
|
70
|
+
data: Object.fromEntries(target.piiFields.map((field) => [field, null])),
|
|
71
|
+
});
|
|
72
|
+
if (count > 0) {
|
|
73
|
+
touched = true;
|
|
74
|
+
anonymizedFields.push(...target.piiFields);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
await params.client.reportErasureResult({
|
|
79
|
+
requestId: request.requestId,
|
|
80
|
+
status: touched ? 'erased' : 'skipped',
|
|
81
|
+
anonymizedFields: anonymizedFields.length > 0 ? anonymizedFields : undefined,
|
|
82
|
+
idempotencyKey: params.idempotencyKey(),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
logger.error('erase', { requestId: request.requestId, error: e });
|
|
87
|
+
await params.client
|
|
88
|
+
.reportErasureResult({
|
|
89
|
+
requestId: request.requestId,
|
|
90
|
+
status: 'failed',
|
|
91
|
+
error: { code: 'erase_failed', message: e instanceof Error ? e.message : 'unknown' },
|
|
92
|
+
idempotencyKey: params.idempotencyKey(),
|
|
93
|
+
})
|
|
94
|
+
.catch(() => undefined);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/worker/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ya-accelerators/web-backend-framework",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.68",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "",
|
|
6
6
|
"author": "YA Technologies OÜ",
|
|
@@ -40,12 +40,15 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@aws-sdk/client-s3": "^3.1048.0",
|
|
43
|
+
"@aws-sdk/credential-provider-node": "^3.972.58",
|
|
43
44
|
"@prisma/adapter-mariadb": "^7.8.0",
|
|
44
45
|
"@prisma/extension-read-replicas": "^0.5.0",
|
|
45
46
|
"@valkey/valkey-glide": "^2.4.0",
|
|
46
47
|
"cors": "^2.8.6",
|
|
47
48
|
"express": "^5.2.1",
|
|
49
|
+
"google-auth-library": "^10.9.0",
|
|
48
50
|
"http-proxy-middleware": "^4.0.0",
|
|
51
|
+
"jose": "^6.2.3",
|
|
49
52
|
"mariadb": "^3.5.2",
|
|
50
53
|
"ulid": "^3.0.2"
|
|
51
54
|
},
|