@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.
Files changed (66) hide show
  1. package/AGENTS.md +30 -0
  2. package/README.md +119 -0
  3. package/dist/client/glueClientFactory.d.ts +3 -0
  4. package/dist/client/glueClientFactory.js +7 -0
  5. package/dist/client/glueClientFactory.js.map +1 -0
  6. package/dist/config/loadConfig.d.ts +7 -0
  7. package/dist/config/loadConfig.js +82 -0
  8. package/dist/config/loadConfig.js.map +1 -0
  9. package/dist/config/schema.d.ts +110 -0
  10. package/dist/config/schema.js +78 -0
  11. package/dist/config/schema.js.map +1 -0
  12. package/dist/domain/contracts.d.ts +65 -0
  13. package/dist/domain/contracts.js +2 -0
  14. package/dist/domain/contracts.js.map +1 -0
  15. package/dist/errors/glueErrors.d.ts +30 -0
  16. package/dist/errors/glueErrors.js +43 -0
  17. package/dist/errors/glueErrors.js.map +1 -0
  18. package/dist/guards/operationGuards.d.ts +4 -0
  19. package/dist/guards/operationGuards.js +28 -0
  20. package/dist/guards/operationGuards.js.map +1 -0
  21. package/dist/index.d.ts +5 -0
  22. package/dist/index.js +4 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/manifest.d.ts +14 -0
  25. package/dist/manifest.js +15 -0
  26. package/dist/manifest.js.map +1 -0
  27. package/dist/openclawEntry.d.ts +8 -0
  28. package/dist/openclawEntry.js +41 -0
  29. package/dist/openclawEntry.js.map +1 -0
  30. package/dist/pluginMetadata.d.ts +5 -0
  31. package/dist/pluginMetadata.js +6 -0
  32. package/dist/pluginMetadata.js.map +1 -0
  33. package/dist/runtime/pluginRuntime.d.ts +22 -0
  34. package/dist/runtime/pluginRuntime.js +47 -0
  35. package/dist/runtime/pluginRuntime.js.map +1 -0
  36. package/dist/services/glueService.d.ts +79 -0
  37. package/dist/services/glueService.js +318 -0
  38. package/dist/services/glueService.js.map +1 -0
  39. package/dist/tools/catalog/catalogTools.d.ts +6 -0
  40. package/dist/tools/catalog/catalogTools.js +108 -0
  41. package/dist/tools/catalog/catalogTools.js.map +1 -0
  42. package/dist/tools/common.d.ts +4 -0
  43. package/dist/tools/common.js +19 -0
  44. package/dist/tools/common.js.map +1 -0
  45. package/dist/tools/registry.d.ts +3 -0
  46. package/dist/tools/registry.js +6 -0
  47. package/dist/tools/registry.js.map +1 -0
  48. package/dist/tools/triggers/triggerTools.d.ts +6 -0
  49. package/dist/tools/triggers/triggerTools.js +157 -0
  50. package/dist/tools/triggers/triggerTools.js.map +1 -0
  51. package/dist/tools/workflows/workflowTools.d.ts +6 -0
  52. package/dist/tools/workflows/workflowTools.js +106 -0
  53. package/dist/tools/workflows/workflowTools.js.map +1 -0
  54. package/dist/utils/sanitize.d.ts +4 -0
  55. package/dist/utils/sanitize.js +34 -0
  56. package/dist/utils/sanitize.js.map +1 -0
  57. package/docs/architecture.md +33 -0
  58. package/docs/roadmap.md +23 -0
  59. package/docs/rollback.md +34 -0
  60. package/docs/threat-model.md +31 -0
  61. package/docs/usage.md +70 -0
  62. package/openclaw.plugin.json +73 -0
  63. package/package.json +57 -0
  64. package/skills/kansodata-glue-operator/SKILL.md +47 -0
  65. package/skills/kansodata-glue-operator/docs/examples.md +44 -0
  66. 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,3 @@
1
+ import { GlueClient } from "@aws-sdk/client-glue";
2
+ import type { GluePluginConfig } from "../config/schema.js";
3
+ export declare const createGlueClient: (config: GluePluginConfig) => GlueClient;
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=contracts.js.map
@@ -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"}
@@ -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";