@kansodata/kansodata-glue-plugin 0.1.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/AGENTS.md +30 -0
- package/README.md +119 -0
- package/dist/client/glueClientFactory.d.ts +3 -0
- package/dist/client/glueClientFactory.js +7 -0
- package/dist/client/glueClientFactory.js.map +1 -0
- package/dist/config/loadConfig.d.ts +7 -0
- package/dist/config/loadConfig.js +82 -0
- package/dist/config/loadConfig.js.map +1 -0
- package/dist/config/schema.d.ts +110 -0
- package/dist/config/schema.js +78 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/domain/contracts.d.ts +65 -0
- package/dist/domain/contracts.js +2 -0
- package/dist/domain/contracts.js.map +1 -0
- package/dist/errors/glueErrors.d.ts +30 -0
- package/dist/errors/glueErrors.js +43 -0
- package/dist/errors/glueErrors.js.map +1 -0
- package/dist/guards/operationGuards.d.ts +4 -0
- package/dist/guards/operationGuards.js +28 -0
- package/dist/guards/operationGuards.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +14 -0
- package/dist/manifest.js +15 -0
- package/dist/manifest.js.map +1 -0
- package/dist/openclawEntry.d.ts +8 -0
- package/dist/openclawEntry.js +41 -0
- package/dist/openclawEntry.js.map +1 -0
- package/dist/pluginMetadata.d.ts +5 -0
- package/dist/pluginMetadata.js +6 -0
- package/dist/pluginMetadata.js.map +1 -0
- package/dist/runtime/pluginRuntime.d.ts +22 -0
- package/dist/runtime/pluginRuntime.js +47 -0
- package/dist/runtime/pluginRuntime.js.map +1 -0
- package/dist/services/glueService.d.ts +79 -0
- package/dist/services/glueService.js +318 -0
- package/dist/services/glueService.js.map +1 -0
- package/dist/tools/catalog/catalogTools.d.ts +6 -0
- package/dist/tools/catalog/catalogTools.js +108 -0
- package/dist/tools/catalog/catalogTools.js.map +1 -0
- package/dist/tools/common.d.ts +4 -0
- package/dist/tools/common.js +19 -0
- package/dist/tools/common.js.map +1 -0
- package/dist/tools/registry.d.ts +3 -0
- package/dist/tools/registry.js +6 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/triggers/triggerTools.d.ts +6 -0
- package/dist/tools/triggers/triggerTools.js +157 -0
- package/dist/tools/triggers/triggerTools.js.map +1 -0
- package/dist/tools/workflows/workflowTools.d.ts +6 -0
- package/dist/tools/workflows/workflowTools.js +106 -0
- package/dist/tools/workflows/workflowTools.js.map +1 -0
- package/dist/utils/sanitize.d.ts +4 -0
- package/dist/utils/sanitize.js +34 -0
- package/dist/utils/sanitize.js.map +1 -0
- package/docs/architecture.md +33 -0
- package/docs/roadmap.md +23 -0
- package/docs/rollback.md +34 -0
- package/docs/threat-model.md +31 -0
- package/docs/usage.md +70 -0
- package/openclaw.plugin.json +73 -0
- package/package.json +57 -0
- package/skills/kansodata-glue-operator/SKILL.md +47 -0
- package/skills/kansodata-glue-operator/docs/examples.md +44 -0
- package/skills/kansodata-glue-operator/docs/scope.md +37 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Repositorio: `@kansodata/kansodata-glue-plugin`
|
|
4
|
+
|
|
5
|
+
## Objetivo operativo V1
|
|
6
|
+
- Proveer plugin OpenClaw para AWS Glue con escritura controlada en workflows/triggers y diagnóstico ETL basado en Glue Catalog/particiones.
|
|
7
|
+
- Operar con fail-closed, guardrails explícitos y documentación suficiente para continuidad.
|
|
8
|
+
|
|
9
|
+
## Límites de alcance V1
|
|
10
|
+
- Permitido: create/update workflow, create/update trigger, lecturas de catálogo y diagnóstico de particiones.
|
|
11
|
+
- Prohibido: create/update/delete Job o Crawler, acciones destructivas por defecto, bypass de validaciones.
|
|
12
|
+
|
|
13
|
+
## Reglas de seguridad
|
|
14
|
+
- Rechazar payloads con patrones obvios de secretos.
|
|
15
|
+
- Restringir writes por allowlist de prefijos cuando esté activa.
|
|
16
|
+
- Exigir read-before-write para updates.
|
|
17
|
+
- Sanitizar mensajes de error y no loggear datos sensibles.
|
|
18
|
+
|
|
19
|
+
## Flujo recomendado
|
|
20
|
+
1. Leer estado actual (`get/list`).
|
|
21
|
+
2. Planificar cambio e impacto.
|
|
22
|
+
3. Validar inputs, alcance y guardrails.
|
|
23
|
+
4. Aplicar (preferir dry-run en cambios nuevos).
|
|
24
|
+
5. Verificar estado posterior.
|
|
25
|
+
|
|
26
|
+
## Validación mínima antes de merge
|
|
27
|
+
- `npm run lint`
|
|
28
|
+
- `npm run typecheck`
|
|
29
|
+
- `npm run build`
|
|
30
|
+
- `npm test`
|
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @kansodata/kansodata-glue-plugin
|
|
2
|
+
|
|
3
|
+
OpenClaw plugin runtime + companion skill for AWS Glue operations with controlled V1 write scope and ETL diagnostics focused on Glue Catalog partition behavior.
|
|
4
|
+
|
|
5
|
+
## V1 Scope
|
|
6
|
+
|
|
7
|
+
### Included
|
|
8
|
+
- Controlled writes:
|
|
9
|
+
- `glue_create_workflow`
|
|
10
|
+
- `glue_update_workflow`
|
|
11
|
+
- `glue_create_trigger`
|
|
12
|
+
- `glue_update_trigger`
|
|
13
|
+
- Operational reads:
|
|
14
|
+
- `glue_list_workflows`
|
|
15
|
+
- `glue_get_workflow`
|
|
16
|
+
- `glue_list_triggers`
|
|
17
|
+
- `glue_get_trigger`
|
|
18
|
+
- `glue_get_catalog_table`
|
|
19
|
+
- `glue_list_catalog_tables`
|
|
20
|
+
- `glue_get_catalog_partitions_sample`
|
|
21
|
+
- `glue_explain_partitioning`
|
|
22
|
+
|
|
23
|
+
### Explicitly excluded in V1
|
|
24
|
+
- Create/update/delete for Glue Jobs.
|
|
25
|
+
- Create/update/delete for Glue Crawlers.
|
|
26
|
+
- Destructive default actions.
|
|
27
|
+
- Unsafe auto-apply flows.
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
- Native OpenClaw plugin entrypoint: `src/openclawEntry.ts` (`definePluginEntry` + `api.registerTool`).
|
|
32
|
+
- `src/runtime`: plugin runtime orchestration and tool dispatch.
|
|
33
|
+
- `src/config`: strict configuration loading and validation.
|
|
34
|
+
- `src/client`: AWS Glue client creation.
|
|
35
|
+
- `src/services`: Glue service adapter with output shaping and safe updates.
|
|
36
|
+
- `src/tools`: V1 tool implementations by domain (`workflows`, `triggers`, `catalog`).
|
|
37
|
+
- `src/guards`: write guards (allowlist, secret detection, read-before-write).
|
|
38
|
+
- `src/errors`: typed error hierarchy.
|
|
39
|
+
- `skills/kansodata-glue-operator`: companion operator skill.
|
|
40
|
+
- `docs`: architecture, threat model, rollback, roadmap, usage.
|
|
41
|
+
|
|
42
|
+
## Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install
|
|
46
|
+
npm run build
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Configuration
|
|
50
|
+
|
|
51
|
+
Effective config keys (OpenClaw `pluginConfig` + env fallback):
|
|
52
|
+
- `region`
|
|
53
|
+
- `profile`
|
|
54
|
+
- `endpointOverride`
|
|
55
|
+
- `allowedNamePrefixes`
|
|
56
|
+
- `enforcePrefixAllowlist`
|
|
57
|
+
- `dryRunByDefault`
|
|
58
|
+
- `maxPartitionSampleSize`
|
|
59
|
+
|
|
60
|
+
Precedence order:
|
|
61
|
+
1. OpenClaw plugin config (`api.pluginConfig`)
|
|
62
|
+
2. Environment variables
|
|
63
|
+
3. Safe defaults already defined in schema (`allowedNamePrefixes`, `enforcePrefixAllowlist`, `dryRunByDefault`, `maxPartitionSampleSize`)
|
|
64
|
+
|
|
65
|
+
Optional:
|
|
66
|
+
- `AWS_PROFILE`
|
|
67
|
+
- `KANSODATA_GLUE_ENDPOINT_OVERRIDE`
|
|
68
|
+
- `KANSODATA_GLUE_ALLOWED_PREFIXES` (comma separated)
|
|
69
|
+
- `KANSODATA_GLUE_ENFORCE_PREFIX_ALLOWLIST` (default `true`)
|
|
70
|
+
- `KANSODATA_GLUE_DRY_RUN_BY_DEFAULT` (default `true`)
|
|
71
|
+
- `KANSODATA_GLUE_MAX_PARTITION_SAMPLE_SIZE` (default `10`, max `25`)
|
|
72
|
+
|
|
73
|
+
Fail-closed behavior:
|
|
74
|
+
- Missing region across OpenClaw config + env fails.
|
|
75
|
+
- Allowlist enforcement with empty prefix list fails.
|
|
76
|
+
- Write operations outside allowed prefixes fail when enforcement is active.
|
|
77
|
+
- Potential secret-like payloads are rejected.
|
|
78
|
+
|
|
79
|
+
## Security and Hardening
|
|
80
|
+
|
|
81
|
+
- Strict TypeScript + strong input validation (`zod`).
|
|
82
|
+
- Error sanitization and explicit error taxonomy.
|
|
83
|
+
- No raw AWS payloads exposed by tools.
|
|
84
|
+
- `glue_update_trigger` accepts only fields that AWS `UpdateTrigger` can really apply (`schedule`, `description`, `actions`, `predicate`).
|
|
85
|
+
- Update tools use controlled fields only, with read-before-write discipline.
|
|
86
|
+
- Dry-run defaults to `true`.
|
|
87
|
+
|
|
88
|
+
## Usage (runtime helpers)
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
import { createPluginRuntime } from "@kansodata/kansodata-glue-plugin";
|
|
92
|
+
|
|
93
|
+
const runtime = createPluginRuntime();
|
|
94
|
+
const result = await runtime.executeTool("glue_list_workflows", { limit: 10 });
|
|
95
|
+
console.log(result.summary, result.data);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
See [docs/usage.md](./docs/usage.md) for more examples.
|
|
99
|
+
|
|
100
|
+
## OpenClaw Wiring
|
|
101
|
+
|
|
102
|
+
- `openclaw.plugin.json` declares plugin id, contracts, config schema, and companion skills (`"./skills"`).
|
|
103
|
+
- `package.json` declares OpenClaw runtime extension entrypoint (`"./dist/openclawEntry.js"`).
|
|
104
|
+
- `src/openclawEntry.ts` is the canonical plugin entry and registers tool contracts via the official OpenClaw SDK.
|
|
105
|
+
|
|
106
|
+
## Plugin/Skill Relationship
|
|
107
|
+
|
|
108
|
+
- Plugin executes controlled AWS Glue operations.
|
|
109
|
+
- Skill governs operational sequence: `read -> plan -> validate -> apply -> verify`.
|
|
110
|
+
- Skill does not replace plugin guardrails; it enforces higher-level operator discipline.
|
|
111
|
+
|
|
112
|
+
## Validation Commands
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
npm run lint
|
|
116
|
+
npm run typecheck
|
|
117
|
+
npm run build
|
|
118
|
+
npm test
|
|
119
|
+
```
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { GlueClient } from "@aws-sdk/client-glue";
|
|
2
|
+
export const createGlueClient = (config) => new GlueClient({
|
|
3
|
+
region: config.region,
|
|
4
|
+
...(config.profile ? { profile: config.profile } : {}),
|
|
5
|
+
...(config.endpointOverride ? { endpoint: config.endpointOverride } : {})
|
|
6
|
+
});
|
|
7
|
+
//# sourceMappingURL=glueClientFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glueClientFactory.js","sourceRoot":"","sources":["../../src/client/glueClientFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAGlD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAwB,EAAc,EAAE,CACvE,IAAI,UAAU,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1E,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type GluePluginConfig } from "./schema.js";
|
|
2
|
+
export interface ResolveConfigOptions {
|
|
3
|
+
readonly openClawConfig?: unknown;
|
|
4
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
5
|
+
}
|
|
6
|
+
export declare const resolveConfig: (options?: ResolveConfigOptions) => GluePluginConfig;
|
|
7
|
+
export declare const loadConfigFromEnv: (env?: NodeJS.ProcessEnv) => GluePluginConfig;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { GluePluginConfigSchema, GluePluginOpenClawConfigSchema } from "./schema.js";
|
|
2
|
+
import { ConfigValidationError } from "../errors/glueErrors.js";
|
|
3
|
+
const TRUE_VALUES = new Set(["1", "true", "yes", "on"]);
|
|
4
|
+
const FALSE_VALUES = new Set(["0", "false", "no", "off"]);
|
|
5
|
+
const parseBoolean = (value, fallback) => {
|
|
6
|
+
if (value === undefined) {
|
|
7
|
+
return fallback;
|
|
8
|
+
}
|
|
9
|
+
const normalized = value.trim().toLowerCase();
|
|
10
|
+
if (TRUE_VALUES.has(normalized)) {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (FALSE_VALUES.has(normalized)) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
throw new ConfigValidationError(`Invalid boolean value: ${value}`);
|
|
17
|
+
};
|
|
18
|
+
const parseOptionalBoolean = (value) => value === undefined ? undefined : parseBoolean(value, false);
|
|
19
|
+
const parseAllowedPrefixes = (raw) => {
|
|
20
|
+
if (!raw) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
return raw
|
|
24
|
+
.split(",")
|
|
25
|
+
.map((part) => part.trim())
|
|
26
|
+
.filter((part) => part.length > 0);
|
|
27
|
+
};
|
|
28
|
+
const parseOptionalNumber = (value) => {
|
|
29
|
+
if (value === undefined) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const parsed = Number(value);
|
|
33
|
+
if (!Number.isFinite(parsed)) {
|
|
34
|
+
throw new ConfigValidationError(`Invalid number value: ${value}`);
|
|
35
|
+
}
|
|
36
|
+
return parsed;
|
|
37
|
+
};
|
|
38
|
+
const toValidationDetails = (issues) => issues.map((issue) => ({
|
|
39
|
+
path: issue.path.join("."),
|
|
40
|
+
message: issue.message
|
|
41
|
+
}));
|
|
42
|
+
export const resolveConfig = (options = {}) => {
|
|
43
|
+
const env = options.env ?? process.env;
|
|
44
|
+
const parsedOpenClawConfig = GluePluginOpenClawConfigSchema.safeParse(options.openClawConfig ?? {});
|
|
45
|
+
if (!parsedOpenClawConfig.success) {
|
|
46
|
+
throw new ConfigValidationError("OpenClaw plugin configuration is invalid.", {
|
|
47
|
+
details: toValidationDetails(parsedOpenClawConfig.error.issues)
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const envCandidate = {
|
|
51
|
+
region: env.AWS_REGION ?? env.AWS_DEFAULT_REGION,
|
|
52
|
+
profile: env.AWS_PROFILE,
|
|
53
|
+
endpointOverride: env.KANSODATA_GLUE_ENDPOINT_OVERRIDE,
|
|
54
|
+
allowedNamePrefixes: env.KANSODATA_GLUE_ALLOWED_PREFIXES === undefined
|
|
55
|
+
? undefined
|
|
56
|
+
: parseAllowedPrefixes(env.KANSODATA_GLUE_ALLOWED_PREFIXES),
|
|
57
|
+
enforcePrefixAllowlist: parseOptionalBoolean(env.KANSODATA_GLUE_ENFORCE_PREFIX_ALLOWLIST),
|
|
58
|
+
dryRunByDefault: parseOptionalBoolean(env.KANSODATA_GLUE_DRY_RUN_BY_DEFAULT),
|
|
59
|
+
maxPartitionSampleSize: parseOptionalNumber(env.KANSODATA_GLUE_MAX_PARTITION_SAMPLE_SIZE)
|
|
60
|
+
};
|
|
61
|
+
const configCandidate = {
|
|
62
|
+
region: parsedOpenClawConfig.data.region ?? envCandidate.region,
|
|
63
|
+
profile: parsedOpenClawConfig.data.profile ?? envCandidate.profile,
|
|
64
|
+
endpointOverride: parsedOpenClawConfig.data.endpointOverride ?? envCandidate.endpointOverride,
|
|
65
|
+
allowedNamePrefixes: parsedOpenClawConfig.data.allowedNamePrefixes ?? envCandidate.allowedNamePrefixes,
|
|
66
|
+
enforcePrefixAllowlist: parsedOpenClawConfig.data.enforcePrefixAllowlist ?? envCandidate.enforcePrefixAllowlist,
|
|
67
|
+
dryRunByDefault: parsedOpenClawConfig.data.dryRunByDefault ?? envCandidate.dryRunByDefault,
|
|
68
|
+
maxPartitionSampleSize: parsedOpenClawConfig.data.maxPartitionSampleSize ?? envCandidate.maxPartitionSampleSize
|
|
69
|
+
};
|
|
70
|
+
const parsed = GluePluginConfigSchema.safeParse(configCandidate);
|
|
71
|
+
if (!parsed.success) {
|
|
72
|
+
throw new ConfigValidationError("Glue plugin configuration is invalid.", {
|
|
73
|
+
details: toValidationDetails(parsed.error.issues)
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (parsed.data.enforcePrefixAllowlist && parsed.data.allowedNamePrefixes.length === 0) {
|
|
77
|
+
throw new ConfigValidationError("Prefix allowlist is enforced but no allowed prefixes were configured.");
|
|
78
|
+
}
|
|
79
|
+
return parsed.data;
|
|
80
|
+
};
|
|
81
|
+
export const loadConfigFromEnv = (env = process.env) => resolveConfig({ env });
|
|
82
|
+
//# sourceMappingURL=loadConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadConfig.js","sourceRoot":"","sources":["../../src/config/loadConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const GLUE_PLUGIN_CONFIG_LIMITS: {
|
|
3
|
+
readonly maxPartitionSampleSize: 25;
|
|
4
|
+
};
|
|
5
|
+
export declare const GLUE_PLUGIN_CONFIG_DEFAULTS: {
|
|
6
|
+
readonly allowedNamePrefixes: string[];
|
|
7
|
+
readonly enforcePrefixAllowlist: true;
|
|
8
|
+
readonly dryRunByDefault: true;
|
|
9
|
+
readonly maxPartitionSampleSize: 10;
|
|
10
|
+
};
|
|
11
|
+
export declare const GluePluginConfigSchema: z.ZodObject<{
|
|
12
|
+
region: z.ZodString;
|
|
13
|
+
profile: z.ZodOptional<z.ZodString>;
|
|
14
|
+
endpointOverride: z.ZodOptional<z.ZodString>;
|
|
15
|
+
allowedNamePrefixes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
16
|
+
enforcePrefixAllowlist: z.ZodDefault<z.ZodBoolean>;
|
|
17
|
+
dryRunByDefault: z.ZodDefault<z.ZodBoolean>;
|
|
18
|
+
maxPartitionSampleSize: z.ZodDefault<z.ZodNumber>;
|
|
19
|
+
}, "strict", z.ZodTypeAny, {
|
|
20
|
+
region: string;
|
|
21
|
+
allowedNamePrefixes: string[];
|
|
22
|
+
enforcePrefixAllowlist: boolean;
|
|
23
|
+
dryRunByDefault: boolean;
|
|
24
|
+
maxPartitionSampleSize: number;
|
|
25
|
+
profile?: string | undefined;
|
|
26
|
+
endpointOverride?: string | undefined;
|
|
27
|
+
}, {
|
|
28
|
+
region: string;
|
|
29
|
+
profile?: string | undefined;
|
|
30
|
+
endpointOverride?: string | undefined;
|
|
31
|
+
allowedNamePrefixes?: string[] | undefined;
|
|
32
|
+
enforcePrefixAllowlist?: boolean | undefined;
|
|
33
|
+
dryRunByDefault?: boolean | undefined;
|
|
34
|
+
maxPartitionSampleSize?: number | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
export declare const GluePluginOpenClawConfigSchema: z.ZodObject<{
|
|
37
|
+
region: z.ZodOptional<z.ZodString>;
|
|
38
|
+
profile: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
39
|
+
endpointOverride: z.ZodOptional<z.ZodOptional<z.ZodString>>;
|
|
40
|
+
allowedNamePrefixes: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodString, "many">>>;
|
|
41
|
+
enforcePrefixAllowlist: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
42
|
+
dryRunByDefault: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
|
|
43
|
+
maxPartitionSampleSize: z.ZodOptional<z.ZodDefault<z.ZodNumber>>;
|
|
44
|
+
}, "strict", z.ZodTypeAny, {
|
|
45
|
+
region?: string | undefined;
|
|
46
|
+
profile?: string | undefined;
|
|
47
|
+
endpointOverride?: string | undefined;
|
|
48
|
+
allowedNamePrefixes?: string[] | undefined;
|
|
49
|
+
enforcePrefixAllowlist?: boolean | undefined;
|
|
50
|
+
dryRunByDefault?: boolean | undefined;
|
|
51
|
+
maxPartitionSampleSize?: number | undefined;
|
|
52
|
+
}, {
|
|
53
|
+
region?: string | undefined;
|
|
54
|
+
profile?: string | undefined;
|
|
55
|
+
endpointOverride?: string | undefined;
|
|
56
|
+
allowedNamePrefixes?: string[] | undefined;
|
|
57
|
+
enforcePrefixAllowlist?: boolean | undefined;
|
|
58
|
+
dryRunByDefault?: boolean | undefined;
|
|
59
|
+
maxPartitionSampleSize?: number | undefined;
|
|
60
|
+
}>;
|
|
61
|
+
export declare const GluePluginOpenClawConfigJsonSchema: {
|
|
62
|
+
readonly type: "object";
|
|
63
|
+
readonly additionalProperties: false;
|
|
64
|
+
readonly properties: {
|
|
65
|
+
readonly region: {
|
|
66
|
+
readonly type: "string";
|
|
67
|
+
readonly minLength: 1;
|
|
68
|
+
readonly description: "AWS region for Glue operations. Fallback: AWS_REGION/AWS_DEFAULT_REGION.";
|
|
69
|
+
};
|
|
70
|
+
readonly profile: {
|
|
71
|
+
readonly type: "string";
|
|
72
|
+
readonly minLength: 1;
|
|
73
|
+
readonly description: "Optional AWS profile. Fallback: AWS_PROFILE.";
|
|
74
|
+
};
|
|
75
|
+
readonly endpointOverride: {
|
|
76
|
+
readonly type: "string";
|
|
77
|
+
readonly format: "uri";
|
|
78
|
+
readonly minLength: 1;
|
|
79
|
+
readonly description: "Optional Glue endpoint override (strict URL validation).";
|
|
80
|
+
};
|
|
81
|
+
readonly allowedNamePrefixes: {
|
|
82
|
+
readonly type: "array";
|
|
83
|
+
readonly items: {
|
|
84
|
+
readonly type: "string";
|
|
85
|
+
readonly minLength: 1;
|
|
86
|
+
};
|
|
87
|
+
readonly default: string[];
|
|
88
|
+
readonly description: "Allowed resource name prefixes for write operations.";
|
|
89
|
+
};
|
|
90
|
+
readonly enforcePrefixAllowlist: {
|
|
91
|
+
readonly type: "boolean";
|
|
92
|
+
readonly default: true;
|
|
93
|
+
readonly description: "When true, writes are rejected outside allowed prefixes.";
|
|
94
|
+
};
|
|
95
|
+
readonly dryRunByDefault: {
|
|
96
|
+
readonly type: "boolean";
|
|
97
|
+
readonly default: true;
|
|
98
|
+
readonly description: "Default write mode. True keeps writes in dry-run unless overridden.";
|
|
99
|
+
};
|
|
100
|
+
readonly maxPartitionSampleSize: {
|
|
101
|
+
readonly type: "integer";
|
|
102
|
+
readonly minimum: 1;
|
|
103
|
+
readonly maximum: 25;
|
|
104
|
+
readonly default: 10;
|
|
105
|
+
readonly description: "Upper bound for partition diagnostics sample size.";
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
export type GluePluginConfig = z.infer<typeof GluePluginConfigSchema>;
|
|
110
|
+
export type GluePluginOpenClawConfigInput = z.infer<typeof GluePluginOpenClawConfigSchema>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const GLUE_PLUGIN_CONFIG_LIMITS = {
|
|
3
|
+
maxPartitionSampleSize: 25
|
|
4
|
+
};
|
|
5
|
+
export const GLUE_PLUGIN_CONFIG_DEFAULTS = {
|
|
6
|
+
allowedNamePrefixes: [],
|
|
7
|
+
enforcePrefixAllowlist: true,
|
|
8
|
+
dryRunByDefault: true,
|
|
9
|
+
maxPartitionSampleSize: 10
|
|
10
|
+
};
|
|
11
|
+
export const GluePluginConfigSchema = z
|
|
12
|
+
.object({
|
|
13
|
+
region: z.string().trim().min(1),
|
|
14
|
+
profile: z.string().trim().min(1).optional(),
|
|
15
|
+
endpointOverride: z.string().trim().url().optional(),
|
|
16
|
+
allowedNamePrefixes: z
|
|
17
|
+
.array(z.string().trim().min(1))
|
|
18
|
+
.default(GLUE_PLUGIN_CONFIG_DEFAULTS.allowedNamePrefixes),
|
|
19
|
+
enforcePrefixAllowlist: z.boolean().default(GLUE_PLUGIN_CONFIG_DEFAULTS.enforcePrefixAllowlist),
|
|
20
|
+
dryRunByDefault: z.boolean().default(GLUE_PLUGIN_CONFIG_DEFAULTS.dryRunByDefault),
|
|
21
|
+
maxPartitionSampleSize: z
|
|
22
|
+
.number()
|
|
23
|
+
.int()
|
|
24
|
+
.positive()
|
|
25
|
+
.max(GLUE_PLUGIN_CONFIG_LIMITS.maxPartitionSampleSize)
|
|
26
|
+
.default(GLUE_PLUGIN_CONFIG_DEFAULTS.maxPartitionSampleSize)
|
|
27
|
+
})
|
|
28
|
+
.strict();
|
|
29
|
+
export const GluePluginOpenClawConfigSchema = GluePluginConfigSchema.partial().strict();
|
|
30
|
+
export const GluePluginOpenClawConfigJsonSchema = {
|
|
31
|
+
type: "object",
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
properties: {
|
|
34
|
+
region: {
|
|
35
|
+
type: "string",
|
|
36
|
+
minLength: 1,
|
|
37
|
+
description: "AWS region for Glue operations. Fallback: AWS_REGION/AWS_DEFAULT_REGION."
|
|
38
|
+
},
|
|
39
|
+
profile: {
|
|
40
|
+
type: "string",
|
|
41
|
+
minLength: 1,
|
|
42
|
+
description: "Optional AWS profile. Fallback: AWS_PROFILE."
|
|
43
|
+
},
|
|
44
|
+
endpointOverride: {
|
|
45
|
+
type: "string",
|
|
46
|
+
format: "uri",
|
|
47
|
+
minLength: 1,
|
|
48
|
+
description: "Optional Glue endpoint override (strict URL validation)."
|
|
49
|
+
},
|
|
50
|
+
allowedNamePrefixes: {
|
|
51
|
+
type: "array",
|
|
52
|
+
items: {
|
|
53
|
+
type: "string",
|
|
54
|
+
minLength: 1
|
|
55
|
+
},
|
|
56
|
+
default: GLUE_PLUGIN_CONFIG_DEFAULTS.allowedNamePrefixes,
|
|
57
|
+
description: "Allowed resource name prefixes for write operations."
|
|
58
|
+
},
|
|
59
|
+
enforcePrefixAllowlist: {
|
|
60
|
+
type: "boolean",
|
|
61
|
+
default: GLUE_PLUGIN_CONFIG_DEFAULTS.enforcePrefixAllowlist,
|
|
62
|
+
description: "When true, writes are rejected outside allowed prefixes."
|
|
63
|
+
},
|
|
64
|
+
dryRunByDefault: {
|
|
65
|
+
type: "boolean",
|
|
66
|
+
default: GLUE_PLUGIN_CONFIG_DEFAULTS.dryRunByDefault,
|
|
67
|
+
description: "Default write mode. True keeps writes in dry-run unless overridden."
|
|
68
|
+
},
|
|
69
|
+
maxPartitionSampleSize: {
|
|
70
|
+
type: "integer",
|
|
71
|
+
minimum: 1,
|
|
72
|
+
maximum: GLUE_PLUGIN_CONFIG_LIMITS.maxPartitionSampleSize,
|
|
73
|
+
default: GLUE_PLUGIN_CONFIG_DEFAULTS.maxPartitionSampleSize,
|
|
74
|
+
description: "Upper bound for partition diagnostics sample size."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,sBAAsB,EAAE,EAAE;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,mBAAmB,EAAE,EAAc;IACnC,sBAAsB,EAAE,IAAI;IAC5B,eAAe,EAAE,IAAI;IACrB,sBAAsB,EAAE,EAAE;CAClB,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC;KACpC,MAAM,CAAC;IACN,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC5C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACpD,mBAAmB,EAAE,CAAC;SACnB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAC/B,OAAO,CAAC,2BAA2B,CAAC,mBAAmB,CAAC;IAC3D,sBAAsB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,sBAAsB,CAAC;IAC/F,eAAe,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC,eAAe,CAAC;IACjF,sBAAsB,EAAE,CAAC;SACtB,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,GAAG,CAAC,yBAAyB,CAAC,sBAAsB,CAAC;SACrD,OAAO,CAAC,2BAA2B,CAAC,sBAAsB,CAAC;CAC/D,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,8BAA8B,GAAG,sBAAsB,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC;AAExF,MAAM,CAAC,MAAM,kCAAkC,GAAG;IAChD,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,0EAA0E;SACxF;QACD,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,8CAA8C;SAC5D;QACD,gBAAgB,EAAE;YAChB,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,CAAC;YACZ,WAAW,EAAE,0DAA0D;SACxE;QACD,mBAAmB,EAAE;YACnB,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,CAAC;aACb;YACD,OAAO,EAAE,2BAA2B,CAAC,mBAAmB;YACxD,WAAW,EAAE,sDAAsD;SACpE;QACD,sBAAsB,EAAE;YACtB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,2BAA2B,CAAC,sBAAsB;YAC3D,WAAW,EAAE,0DAA0D;SACxE;QACD,eAAe,EAAE;YACf,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,2BAA2B,CAAC,eAAe;YACpD,WAAW,EAAE,qEAAqE;SACnF;QACD,sBAAsB,EAAE;YACtB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,yBAAyB,CAAC,sBAAsB;YACzD,OAAO,EAAE,2BAA2B,CAAC,sBAAsB;YAC3D,WAAW,EAAE,oDAAoD;SAClE;KACF;CACO,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { GluePluginConfig } from "../config/schema.js";
|
|
2
|
+
import type { GlueService } from "../services/glueService.js";
|
|
3
|
+
export type ToolName = "glue_list_workflows" | "glue_get_workflow" | "glue_create_workflow" | "glue_update_workflow" | "glue_list_triggers" | "glue_get_trigger" | "glue_create_trigger" | "glue_update_trigger" | "glue_get_catalog_table" | "glue_list_catalog_tables" | "glue_get_catalog_partitions_sample" | "glue_explain_partitioning";
|
|
4
|
+
export interface ToolExecutionContext {
|
|
5
|
+
readonly config: GluePluginConfig;
|
|
6
|
+
readonly glueService: GlueService;
|
|
7
|
+
}
|
|
8
|
+
export interface ToolExecutionResult {
|
|
9
|
+
readonly summary: string;
|
|
10
|
+
readonly data: Record<string, unknown>;
|
|
11
|
+
readonly warnings?: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export interface ToolDefinition<TInput> {
|
|
14
|
+
readonly name: ToolName;
|
|
15
|
+
readonly description: string;
|
|
16
|
+
readonly inputSchema: Record<string, unknown>;
|
|
17
|
+
execute(context: ToolExecutionContext, input: unknown): Promise<ToolExecutionResult>;
|
|
18
|
+
parseInput(input: unknown): TInput;
|
|
19
|
+
}
|
|
20
|
+
export interface GlueWorkflowView {
|
|
21
|
+
readonly name: string;
|
|
22
|
+
readonly description?: string;
|
|
23
|
+
readonly maxConcurrentRuns?: number;
|
|
24
|
+
readonly defaultRunProperties?: Readonly<Record<string, string>>;
|
|
25
|
+
readonly graphSummary?: {
|
|
26
|
+
readonly nodeCount: number;
|
|
27
|
+
readonly edgeCount: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface GlueTriggerView {
|
|
31
|
+
readonly name: string;
|
|
32
|
+
readonly type?: string;
|
|
33
|
+
readonly state?: string;
|
|
34
|
+
readonly workflowName?: string;
|
|
35
|
+
readonly schedule?: string;
|
|
36
|
+
readonly description?: string;
|
|
37
|
+
readonly actionJobNames: readonly string[];
|
|
38
|
+
readonly predicateSummary?: {
|
|
39
|
+
readonly logical?: string;
|
|
40
|
+
readonly conditions: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface CatalogTableView {
|
|
44
|
+
readonly databaseName: string;
|
|
45
|
+
readonly tableName: string;
|
|
46
|
+
readonly owner?: string;
|
|
47
|
+
readonly tableType?: string;
|
|
48
|
+
readonly location?: string;
|
|
49
|
+
readonly parameters: Readonly<Record<string, string>>;
|
|
50
|
+
readonly partitionKeys: readonly string[];
|
|
51
|
+
readonly storageDescriptorColumns: readonly string[];
|
|
52
|
+
}
|
|
53
|
+
export interface CatalogPartitionSample {
|
|
54
|
+
readonly values: readonly string[];
|
|
55
|
+
readonly location?: string;
|
|
56
|
+
readonly creationTime?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface PartitioningExplainView {
|
|
59
|
+
readonly databaseName: string;
|
|
60
|
+
readonly tableName: string;
|
|
61
|
+
readonly partitionKeys: readonly string[];
|
|
62
|
+
readonly sampleCount: number;
|
|
63
|
+
readonly sampleValues: readonly string[];
|
|
64
|
+
readonly guidance: readonly string[];
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/domain/contracts.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type ErrorMetadata = Readonly<Record<string, unknown>>;
|
|
2
|
+
export declare class GluePluginError extends Error {
|
|
3
|
+
readonly code: string;
|
|
4
|
+
readonly status: number;
|
|
5
|
+
readonly metadata?: ErrorMetadata;
|
|
6
|
+
constructor(message: string, options: {
|
|
7
|
+
code: string;
|
|
8
|
+
status: number;
|
|
9
|
+
metadata?: ErrorMetadata;
|
|
10
|
+
cause?: unknown;
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export declare class ConfigValidationError extends GluePluginError {
|
|
14
|
+
constructor(message: string, metadata?: ErrorMetadata);
|
|
15
|
+
}
|
|
16
|
+
export declare class MissingAuthorizationError extends GluePluginError {
|
|
17
|
+
constructor(message?: string, metadata?: ErrorMetadata);
|
|
18
|
+
}
|
|
19
|
+
export declare class InvalidInputError extends GluePluginError {
|
|
20
|
+
constructor(message: string, metadata?: ErrorMetadata);
|
|
21
|
+
}
|
|
22
|
+
export declare class ResourceNotFoundError extends GluePluginError {
|
|
23
|
+
constructor(message: string, metadata?: ErrorMetadata);
|
|
24
|
+
}
|
|
25
|
+
export declare class UnsafeOperationError extends GluePluginError {
|
|
26
|
+
constructor(message: string, metadata?: ErrorMetadata);
|
|
27
|
+
}
|
|
28
|
+
export declare class RemoteServiceError extends GluePluginError {
|
|
29
|
+
constructor(message: string, metadata?: ErrorMetadata, cause?: unknown);
|
|
30
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class GluePluginError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
metadata;
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message, { cause: options.cause });
|
|
7
|
+
this.name = this.constructor.name;
|
|
8
|
+
this.code = options.code;
|
|
9
|
+
this.status = options.status;
|
|
10
|
+
this.metadata = options.metadata;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class ConfigValidationError extends GluePluginError {
|
|
14
|
+
constructor(message, metadata) {
|
|
15
|
+
super(message, { code: "CONFIG_INVALID", status: 400, metadata });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class MissingAuthorizationError extends GluePluginError {
|
|
19
|
+
constructor(message = "AWS credentials are missing or invalid.", metadata) {
|
|
20
|
+
super(message, { code: "AUTH_MISSING", status: 401, metadata });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class InvalidInputError extends GluePluginError {
|
|
24
|
+
constructor(message, metadata) {
|
|
25
|
+
super(message, { code: "INPUT_INVALID", status: 400, metadata });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export class ResourceNotFoundError extends GluePluginError {
|
|
29
|
+
constructor(message, metadata) {
|
|
30
|
+
super(message, { code: "RESOURCE_NOT_FOUND", status: 404, metadata });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export class UnsafeOperationError extends GluePluginError {
|
|
34
|
+
constructor(message, metadata) {
|
|
35
|
+
super(message, { code: "UNSAFE_OPERATION", status: 403, metadata });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class RemoteServiceError extends GluePluginError {
|
|
39
|
+
constructor(message, metadata, cause) {
|
|
40
|
+
super(message, { code: "REMOTE_ERROR", status: 502, metadata, cause });
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=glueErrors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glueErrors.js","sourceRoot":"","sources":["../../src/errors/glueErrors.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IACxB,IAAI,CAAS;IACb,MAAM,CAAS;IACf,QAAQ,CAAiB;IAEzC,YACE,OAAe,EACf,OAKC;QAED,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IACxD,YAAmB,OAAe,EAAE,QAAwB;QAC1D,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,eAAe;IAC5D,YAAmB,OAAO,GAAG,yCAAyC,EAAE,QAAwB;QAC9F,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClE,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,eAAe;IACpD,YAAmB,OAAe,EAAE,QAAwB;QAC1D,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnE,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IACxD,YAAmB,OAAe,EAAE,QAAwB;QAC1D,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxE,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,eAAe;IACvD,YAAmB,OAAe,EAAE,QAAwB;QAC1D,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,eAAe;IACrD,YAAmB,OAAe,EAAE,QAAwB,EAAE,KAAe;QAC3E,KAAK,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,CAAC;CACF"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { GluePluginConfig } from "../config/schema.js";
|
|
2
|
+
export declare const assertNoSecretsInPayload: (payload: unknown) => void;
|
|
3
|
+
export declare const assertNameAllowedByPrefix: (config: GluePluginConfig, resourceName: string, resourceType: "workflow" | "trigger") => void;
|
|
4
|
+
export declare const assertReadBeforeWrite: (existing: unknown, resourceType: "workflow" | "trigger", resourceName: string) => void;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { InvalidInputError, UnsafeOperationError } from "../errors/glueErrors.js";
|
|
2
|
+
import { hasPotentialSecret } from "../utils/sanitize.js";
|
|
3
|
+
const startsWithAny = (value, prefixes) => prefixes.some((prefix) => value.startsWith(prefix));
|
|
4
|
+
export const assertNoSecretsInPayload = (payload) => {
|
|
5
|
+
if (hasPotentialSecret(payload)) {
|
|
6
|
+
throw new UnsafeOperationError("Payload rejected because it appears to contain secrets.");
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
export const assertNameAllowedByPrefix = (config, resourceName, resourceType) => {
|
|
10
|
+
if (!resourceName.trim()) {
|
|
11
|
+
throw new InvalidInputError(`${resourceType} name cannot be empty.`);
|
|
12
|
+
}
|
|
13
|
+
if (!config.enforcePrefixAllowlist) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (!startsWithAny(resourceName, config.allowedNamePrefixes)) {
|
|
17
|
+
throw new UnsafeOperationError(`${resourceType} "${resourceName}" is outside allowed prefixes.`, {
|
|
18
|
+
resourceType,
|
|
19
|
+
resourceName
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
export const assertReadBeforeWrite = (existing, resourceType, resourceName) => {
|
|
24
|
+
if (!existing) {
|
|
25
|
+
throw new UnsafeOperationError(`Cannot update ${resourceType} "${resourceName}" because baseline state is unavailable.`);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=operationGuards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operationGuards.js","sourceRoot":"","sources":["../../src/guards/operationGuards.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAClF,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,MAAM,aAAa,GAAG,CAAC,KAAa,EAAE,QAA2B,EAAW,EAAE,CAC5E,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAEtD,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAgB,EAAQ,EAAE;IACjE,IAAI,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,oBAAoB,CAAC,yDAAyD,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,MAAwB,EACxB,YAAoB,EACpB,YAAoC,EAC9B,EAAE;IACR,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,iBAAiB,CAAC,GAAG,YAAY,wBAAwB,CAAC,CAAC;IACvE,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,sBAAsB,EAAE,CAAC;QACnC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC7D,MAAM,IAAI,oBAAoB,CAC5B,GAAG,YAAY,KAAK,YAAY,gCAAgC,EAChE;YACE,YAAY;YACZ,YAAY;SACb,CACF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,QAAiB,EACjB,YAAoC,EACpC,YAAoB,EACd,EAAE;IACR,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,oBAAoB,CAC5B,iBAAiB,YAAY,KAAK,YAAY,0CAA0C,CACzF,CAAC;IACJ,CAAC;AACH,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createManifest } from "./manifest.js";
|
|
2
|
+
export { createPluginRuntime } from "./runtime/pluginRuntime.js";
|
|
3
|
+
export { loadConfigFromEnv, resolveConfig } from "./config/loadConfig.js";
|
|
4
|
+
export type { GluePluginConfig } from "./config/schema.js";
|
|
5
|
+
export type { OpenClawPluginRuntime, RuntimeOptions, ToolErrorPayload } from "./runtime/pluginRuntime.js";
|