@pikku/cli 0.12.91 → 0.12.92
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/LICENSE +106 -0
- package/console-app/assets/{index-CpkvmAGb.js → index-DDpIMCpy.js} +149 -149
- package/console-app/index.html +1 -1
- package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
- package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-channel.js +6 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +15 -0
- package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +21 -0
- package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
- package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
- package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
- package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
- package/dist/.pikku/function/pikku-functions-meta.gen.json +35 -40
- package/dist/.pikku/function/pikku-functions.gen.js +1 -3
- package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
- package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
- package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +2 -1
- package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +2 -1
- package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
- package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
- package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
- package/dist/.pikku/pikku-meta-service.gen.js +1 -1
- package/dist/.pikku/pikku-services.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.d.ts +1 -1
- package/dist/.pikku/pikku-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
- package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
- package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
- package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
- package/dist/.pikku/scenarios/schemas/register.gen.d.ts +4 -0
- package/dist/.pikku/scenarios/schemas/register.gen.js +4 -0
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
- package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
- package/dist/.pikku/schemas/register.gen.js +5 -3
- package/dist/.pikku/schemas/schemas/FabricSecretsListOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/FabricSecretsRotateInput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricSecretsRotateOutput.schema.json +1 -0
- package/dist/.pikku/schemas/schemas/FabricSecretsSetOutput.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
- package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
- package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
- package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
- package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
- package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
- package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
- package/dist/.pikku/workflow/meta/allWorkflow.gen.json +2 -8
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-scenario-actors.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
- package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
- package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
- package/dist/bin/pikku-bin.mjs +2 -2
- package/dist/src/cli.wiring.js +6 -0
- package/dist/src/deploy/analyzer/analyzer.js +22 -5
- package/dist/src/deploy/build-pipeline.js +5 -1
- package/dist/src/fabric/fabric-commands.d.ts +37 -9
- package/dist/src/fabric/fabric-commands.js +12 -0
- package/dist/src/fabric/functions/domains-add.function.d.ts +4 -4
- package/dist/src/fabric/functions/secrets-list.function.d.ts +16 -4
- package/dist/src/fabric/functions/secrets-list.function.js +12 -10
- package/dist/src/fabric/functions/secrets-rotate.function.d.ts +24 -0
- package/dist/src/fabric/functions/secrets-rotate.function.js +36 -0
- package/dist/src/fabric/functions/secrets-set.function.d.ts +8 -4
- package/dist/src/fabric/functions/secrets-set.function.js +18 -7
- package/dist/src/fabric/lib/http.d.ts +7 -1
- package/dist/src/fabric/lib/sealed-box.d.ts +16 -0
- package/dist/src/fabric/lib/sealed-box.js +72 -0
- package/dist/src/functions/commands/dev.js +9 -0
- package/dist/src/functions/commands/pikku-command-bootstrap.js +1 -0
- package/dist/src/functions/commands/scenario-browser.d.ts +17 -2
- package/dist/src/functions/commands/scenario-browser.js +16 -8
- package/dist/src/functions/commands/scenario-environment.d.ts +32 -0
- package/dist/src/functions/commands/scenario-environment.js +61 -0
- package/dist/src/functions/commands/scenario.d.ts +6 -0
- package/dist/src/functions/commands/scenario.js +14 -9
- package/dist/src/functions/commands/skills.js +27 -61
- package/dist/src/functions/db/db-codegen.d.ts +6 -0
- package/dist/src/functions/db/db-codegen.js +9 -0
- package/dist/src/functions/db/db-migrator.js +14 -0
- package/dist/src/functions/db/local-db.d.ts +8 -0
- package/dist/src/functions/db/local-db.js +24 -2
- package/dist/src/functions/db/migration-identifiers.d.ts +58 -0
- package/dist/src/functions/db/migration-identifiers.js +262 -0
- package/dist/src/functions/db/migration-provenance.d.ts +35 -0
- package/dist/src/functions/db/migration-provenance.js +80 -0
- package/dist/src/functions/db/schema-sql.d.ts +43 -0
- package/dist/src/functions/db/schema-sql.js +135 -0
- package/dist/src/functions/db/sqlite/sqlite-kysely.js +22 -2
- package/dist/src/functions/wirings/functions/schemas.js +13 -1
- package/dist/src/functions/wirings/rpc/pikku-command-rpc.js +6 -1
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +10 -0
- package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +102 -0
- package/dist/src/functions/wirings/scenarios/scenario-partition.d.ts +13 -0
- package/dist/src/functions/wirings/scenarios/scenario-partition.js +15 -2
- package/dist/src/functions/wirings/scenarios/scenario-schema-partition.d.ts +33 -0
- package/dist/src/functions/wirings/scenarios/scenario-schema-partition.js +49 -0
- package/dist/src/functions/workflows/all.workflow.js +2 -7
- package/dist/src/utils/file-writer.js +14 -2
- package/dist/src/utils/pikku-cli-config.d.ts +14 -0
- package/dist/src/utils/pikku-cli-config.js +34 -0
- package/dist/src/utils/remove-legacy-scaffold-file.d.ts +14 -0
- package/dist/src/utils/remove-legacy-scaffold-file.js +23 -0
- package/dist/src/utils/serialize-schemas.d.ts +3 -1
- package/dist/src/utils/serialize-schemas.js +39 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/dist/.pikku/schemas/schemas/PikkuScenarioFunctionsOutput.schema.json +0 -1
- package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.d.ts +0 -1
- package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.js +0 -31
- package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.d.ts +0 -10
- package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.js +0 -104
- package/skills/pikku-addon/SKILL.md +0 -243
- package/skills/pikku-addon/references/addon-package-manifest.md +0 -63
- package/skills/pikku-ai-agent/SKILL.md +0 -231
- package/skills/pikku-ai-vercel/SKILL.md +0 -82
- package/skills/pikku-ai-voice/SKILL.md +0 -88
- package/skills/pikku-audit/SKILL.md +0 -175
- package/skills/pikku-aws/SKILL.md +0 -111
- package/skills/pikku-backblaze/SKILL.md +0 -71
- package/skills/pikku-better-auth/SKILL.md +0 -298
- package/skills/pikku-cli/SKILL.md +0 -198
- package/skills/pikku-cli/references/complete-example.md +0 -82
- package/skills/pikku-concepts/SKILL.md +0 -250
- package/skills/pikku-concepts/references/concept-mapping.md +0 -556
- package/skills/pikku-concepts/references/packages.md +0 -29
- package/skills/pikku-config/SKILL.md +0 -212
- package/skills/pikku-cron/SKILL.md +0 -214
- package/skills/pikku-deploy-azure/SKILL.md +0 -71
- package/skills/pikku-deploy-cloudflare/SKILL.md +0 -82
- package/skills/pikku-deploy-express/SKILL.md +0 -86
- package/skills/pikku-deploy-fastify/SKILL.md +0 -73
- package/skills/pikku-deploy-lambda/SKILL.md +0 -110
- package/skills/pikku-deploy-nextjs/SKILL.md +0 -78
- package/skills/pikku-deploy-uws/SKILL.md +0 -88
- package/skills/pikku-deps/SKILL.md +0 -98
- package/skills/pikku-emails/SKILL.md +0 -163
- package/skills/pikku-fabric/SKILL.md +0 -318
- package/skills/pikku-fabric-debug/SKILL.md +0 -112
- package/skills/pikku-feature/SKILL.md +0 -258
- package/skills/pikku-gateway-slack/SKILL.md +0 -115
- package/skills/pikku-http/SKILL.md +0 -220
- package/skills/pikku-http/references/http-options.md +0 -55
- package/skills/pikku-i18n/SKILL.md +0 -137
- package/skills/pikku-info/SKILL.md +0 -100
- package/skills/pikku-jose/SKILL.md +0 -105
- package/skills/pikku-kysely/SKILL.md +0 -219
- package/skills/pikku-machine-auth/SKILL.md +0 -183
- package/skills/pikku-mcp/SKILL.md +0 -241
- package/skills/pikku-middleware/SKILL.md +0 -231
- package/skills/pikku-middleware/references/middleware-patterns.md +0 -61
- package/skills/pikku-mongodb/SKILL.md +0 -105
- package/skills/pikku-n8n-import/SKILL.md +0 -109
- package/skills/pikku-n8n-import/SPEC.md +0 -84
- package/skills/pikku-n8n-import/references/addon-mapping.md +0 -121
- package/skills/pikku-n8n-import/references/code-translation.md +0 -121
- package/skills/pikku-n8n-import/references/loops-and-control.md +0 -87
- package/skills/pikku-paraglide/SKILL.md +0 -117
- package/skills/pikku-permissions/SKILL.md +0 -192
- package/skills/pikku-pino/SKILL.md +0 -79
- package/skills/pikku-product-second-opinion/README.md +0 -43
- package/skills/pikku-product-second-opinion/SKILL.md +0 -158
- package/skills/pikku-product-second-opinion/example/sample-report.md +0 -90
- package/skills/pikku-product-second-opinion/references/report-template.md +0 -73
- package/skills/pikku-queue/SKILL.md +0 -240
- package/skills/pikku-react/SKILL.md +0 -212
- package/skills/pikku-react-query/SKILL.md +0 -242
- package/skills/pikku-realtime/SKILL.md +0 -236
- package/skills/pikku-realtime/references/other-routes.md +0 -23
- package/skills/pikku-redis/SKILL.md +0 -90
- package/skills/pikku-rpc/SKILL.md +0 -171
- package/skills/pikku-rtl/SKILL.md +0 -219
- package/skills/pikku-scenario/SKILL.md +0 -382
- package/skills/pikku-schedule/SKILL.md +0 -57
- package/skills/pikku-schema-ajv/SKILL.md +0 -62
- package/skills/pikku-schema-cfworker/SKILL.md +0 -63
- package/skills/pikku-security/SKILL.md +0 -108
- package/skills/pikku-services/SKILL.md +0 -248
- package/skills/pikku-services/references/audit-wire-service.md +0 -34
- package/skills/pikku-software-archaeology/README.md +0 -70
- package/skills/pikku-software-archaeology/SKILL.md +0 -186
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +0 -625
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +0 -49
- package/skills/pikku-software-archaeology/scripts/validate.mjs +0 -173
- package/skills/pikku-tag-middleware/SKILL.md +0 -13
- package/skills/pikku-template-clone/SKILL.md +0 -40
- package/skills/pikku-trigger/SKILL.md +0 -181
- package/skills/pikku-versioning/SKILL.md +0 -173
- package/skills/pikku-websocket/SKILL.md +0 -243
- package/skills/pikku-workflow/SKILL.md +0 -172
- package/skills/pikku-workflow/references/workflow-reference.md +0 -63
- package/skills/pikku-workflows-client/SKILL.md +0 -150
- package/skills/pikku-ws/SKILL.md +0 -47
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-schema-ajv
|
|
3
|
-
description: >-
|
|
4
|
-
Use when setting up JSON schema validation with AJV in a Pikku app. Covers AjvSchemaService for
|
|
5
|
-
request/response validation. TRIGGER when: code uses AjvSchemaService, user asks about AJV, JSON
|
|
6
|
-
schema validation, or @pikku/schema-ajv. DO NOT TRIGGER when: user asks about Cloudflare Workers
|
|
7
|
-
schema validation (use pikku-schema-cfworker).
|
|
8
|
-
installGroups: [core]
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
# Pikku Schema AJV (JSON Schema Validation)
|
|
12
|
-
|
|
13
|
-
## Agent Operating Procedure
|
|
14
|
-
|
|
15
|
-
Use this skill as an execution checklist, not reference material.
|
|
16
|
-
|
|
17
|
-
1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
|
|
18
|
-
2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
|
|
19
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
20
|
-
4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
|
|
21
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
22
|
-
|
|
23
|
-
`@pikku/schema-ajv` provides JSON schema validation using [AJV](https://ajv.js.org/). Implements the `SchemaService` interface from `@pikku/core`. This is the default schema validator for Node.js environments.
|
|
24
|
-
|
|
25
|
-
## Installation
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
yarn add @pikku/schema-ajv
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
## API Reference
|
|
32
|
-
|
|
33
|
-
### `AjvSchemaService`
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { AjvSchemaService } from '@pikku/schema-ajv'
|
|
37
|
-
|
|
38
|
-
const schema = new AjvSchemaService(logger: Logger)
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
**Methods:**
|
|
42
|
-
|
|
43
|
-
- `compileSchema(schema: string, value: any): void` — Compile and register a JSON schema
|
|
44
|
-
- `validateSchema(schemaName: string, json: any): void` — Validate data against a compiled schema (throws on failure)
|
|
45
|
-
- `getSchemaNames(): Set<string>` — Get all registered schema names
|
|
46
|
-
- `getSchemaKeys(schemaName: string): string[]` — Get property keys for a schema
|
|
47
|
-
|
|
48
|
-
## Usage Patterns
|
|
49
|
-
|
|
50
|
-
### With Pikku Services
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import { AjvSchemaService } from '@pikku/schema-ajv'
|
|
54
|
-
|
|
55
|
-
const createSingletonServices = pikkuServices(async (config) => {
|
|
56
|
-
const logger = new ConsoleLogger()
|
|
57
|
-
const schema = new AjvSchemaService(logger)
|
|
58
|
-
return { config, logger, schema }
|
|
59
|
-
})
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Pikku automatically uses the schema service to validate function inputs and outputs when schemas are defined in your function definitions.
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-schema-cfworker
|
|
3
|
-
description: >-
|
|
4
|
-
Use when setting up JSON schema validation for Cloudflare Workers in a Pikku app. Covers
|
|
5
|
-
CFWorkerSchemaService as a lightweight alternative to AJV. TRIGGER when: code uses
|
|
6
|
-
CFWorkerSchemaService, user asks about schema validation on Cloudflare Workers, or
|
|
7
|
-
@pikku/schema-cfworker. DO NOT TRIGGER when: user asks about AJV schema validation (use
|
|
8
|
-
pikku-schema-ajv).
|
|
9
|
-
installGroups: [core, fabric]
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
# Pikku Schema CFWorker (Cloudflare Workers Validation)
|
|
13
|
-
|
|
14
|
-
## Agent Operating Procedure
|
|
15
|
-
|
|
16
|
-
Use this skill as an execution checklist, not reference material.
|
|
17
|
-
|
|
18
|
-
1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
|
|
19
|
-
2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
|
|
20
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
21
|
-
4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
|
|
22
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
23
|
-
|
|
24
|
-
`@pikku/schema-cfworker` provides JSON schema validation using [@cfworker/json-schema](https://github.com/cfworker/cfworker), a lightweight validator compatible with Cloudflare Workers (no `eval` or `new Function`). Implements the `SchemaService` interface from `@pikku/core`.
|
|
25
|
-
|
|
26
|
-
## Installation
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
yarn add @pikku/schema-cfworker
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## API Reference
|
|
33
|
-
|
|
34
|
-
### `CFWorkerSchemaService`
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { CFWorkerSchemaService } from '@pikku/schema-cfworker'
|
|
38
|
-
|
|
39
|
-
const schema = new CFWorkerSchemaService(logger: Logger)
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Methods:**
|
|
43
|
-
|
|
44
|
-
- `compileSchema(schema: string, value: any): void` — Compile and register a JSON schema
|
|
45
|
-
- `validateSchema(schemaName: string, json: any): void` — Validate data against a compiled schema (throws on failure)
|
|
46
|
-
- `getSchemaNames(): Set<string>` — Get all registered schema names
|
|
47
|
-
- `getSchemaKeys(schemaName: string): string[]` — Get property keys for a schema
|
|
48
|
-
|
|
49
|
-
## Usage Patterns
|
|
50
|
-
|
|
51
|
-
### With Cloudflare Workers
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
import { CFWorkerSchemaService } from '@pikku/schema-cfworker'
|
|
55
|
-
|
|
56
|
-
const createSingletonServices = pikkuServices(async (config) => {
|
|
57
|
-
const logger = new ConsoleLogger()
|
|
58
|
-
const schema = new CFWorkerSchemaService(logger)
|
|
59
|
-
return { config, logger, schema }
|
|
60
|
-
})
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Use this instead of `@pikku/schema-ajv` when deploying to Cloudflare Workers, as AJV uses `eval` which is not permitted in the Workers runtime.
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-security
|
|
3
|
-
description: >-
|
|
4
|
-
Use when adding authentication or session management to a Pikku app — pikkuAuth, session
|
|
5
|
-
lifecycle (setSession/clearSession), built-in auth strategies (authBearer, authCookie,
|
|
6
|
-
authAPIKey), or JWT setup. TRIGGER when: user asks about login, logout, session, bearer tokens,
|
|
7
|
-
cookie auth, API keys, or JWT. DO NOT TRIGGER when: user asks about middleware (use
|
|
8
|
-
pikku-middleware), permissions/authorization checks (use pikku-permissions), or secrets/env vars
|
|
9
|
-
(use pikku-config).
|
|
10
|
-
installGroups: [core]
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Pikku Security (Authentication & Sessions)
|
|
14
|
-
|
|
15
|
-
## Agent Operating Procedure
|
|
16
|
-
|
|
17
|
-
1. Discover before editing. Run `pikku info middleware --verbose` and `pikku info functions --verbose` to understand existing auth setup.
|
|
18
|
-
2. Auth strategies live in wirings files — do not put `addHTTPMiddleware` calls inside function bodies.
|
|
19
|
-
3. Validate with `pikku all --tsc` after changes — it regenerates and then type-checks in one pass, and fails on type errors. Use `--tsc-summary` for a compact one-line-per-error report.
|
|
20
|
-
|
|
21
|
-
For **middleware** (including tag middleware and service-to-service bearer auth) see `pikku-middleware`.
|
|
22
|
-
For **permissions** (pikkuPermission, pikkuAuth, per-function authorization) see `pikku-permissions`.
|
|
23
|
-
|
|
24
|
-
## Session Management
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
// Read session in pikkuFunc (session guaranteed to exist)
|
|
28
|
-
const getProfile = pikkuFunc({
|
|
29
|
-
func: async ({ db }, _data, { session }) => {
|
|
30
|
-
return await db.getUser(session.userId)
|
|
31
|
-
},
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
// Set session (e.g., after login)
|
|
35
|
-
const login = pikkuFunc({
|
|
36
|
-
auth: false,
|
|
37
|
-
func: async ({ jwt, db }, { email, password }, { setSession }) => {
|
|
38
|
-
const user = await db.verifyCredentials(email, password)
|
|
39
|
-
setSession({ userId: user.id })
|
|
40
|
-
return { token: jwt.sign({ userId: user.id }) }
|
|
41
|
-
},
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
// Clear session (logout)
|
|
45
|
-
const logout = pikkuFunc({
|
|
46
|
-
func: async ({}, _data, { clearSession }) => {
|
|
47
|
-
clearSession()
|
|
48
|
-
},
|
|
49
|
-
})
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Built-in Auth Strategies
|
|
53
|
-
|
|
54
|
-
Apply these via `addHTTPMiddleware` in a wirings file:
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
import { authBearer, authCookie, authAPIKey } from '@pikku/core/middleware'
|
|
58
|
-
import { addHTTPMiddleware } from '@pikku/core/http'
|
|
59
|
-
|
|
60
|
-
// JWT bearer token — reads Authorization header
|
|
61
|
-
addHTTPMiddleware('*', [authBearer()])
|
|
62
|
-
|
|
63
|
-
// Cookie-based sessions — auto-refreshes JWT
|
|
64
|
-
addHTTPMiddleware('*', [
|
|
65
|
-
authCookie({
|
|
66
|
-
name: 'session',
|
|
67
|
-
expiresIn: { value: 30, unit: 'day' },
|
|
68
|
-
options: { httpOnly: true, secure: true },
|
|
69
|
-
}),
|
|
70
|
-
])
|
|
71
|
-
|
|
72
|
-
// API key — from x-api-key header or ?apiKey= query param
|
|
73
|
-
addHTTPMiddleware('*', [authAPIKey({ source: 'all' })])
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Complete Example
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
// permissions.ts
|
|
80
|
-
import { pikkuAuth, pikkuPermission } from '#pikku'
|
|
81
|
-
|
|
82
|
-
export const isAuthenticated = pikkuAuth(async (_services, session) => !!session)
|
|
83
|
-
export const isVerified = pikkuAuth(async (_services, session) => !!session?.emailVerified)
|
|
84
|
-
|
|
85
|
-
// wirings/auth.wiring.ts
|
|
86
|
-
import { authCookie } from '@pikku/core/middleware'
|
|
87
|
-
import { addHTTPMiddleware } from '@pikku/core/http'
|
|
88
|
-
|
|
89
|
-
addHTTPMiddleware('*', [
|
|
90
|
-
authCookie({ name: 'session', expiresIn: { value: 30, unit: 'day' } }),
|
|
91
|
-
])
|
|
92
|
-
|
|
93
|
-
// functions/auth.functions.ts
|
|
94
|
-
export const login = pikkuFunc({
|
|
95
|
-
auth: false,
|
|
96
|
-
func: async ({ jwt, db }, { email, password }, { setSession }) => {
|
|
97
|
-
const user = await db.verifyCredentials(email, password)
|
|
98
|
-
setSession({ userId: user.id })
|
|
99
|
-
return { token: jwt.sign({ userId: user.id }) }
|
|
100
|
-
},
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
export const logout = pikkuFunc({
|
|
104
|
-
func: async ({}, _data, { clearSession }) => {
|
|
105
|
-
clearSession()
|
|
106
|
-
},
|
|
107
|
-
})
|
|
108
|
-
```
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-services
|
|
3
|
-
description: >-
|
|
4
|
-
Use when setting up dependency injection, creating custom services, or configuring the service
|
|
5
|
-
layer in a Pikku app. Covers pikkuServices (singleton), pikkuWireServices (per-request), service
|
|
6
|
-
typing, built-in services, and tree-shaking. TRIGGER when: code uses
|
|
7
|
-
pikkuServices/pikkuWireServices, user asks about services.ts, dependency injection, service
|
|
8
|
-
factories, or built-in services (ConsoleLogger, JoseJWTService). DO NOT TRIGGER when: user asks
|
|
9
|
-
about auth middleware (use pikku-security) or secrets/variables (use pikku-config).
|
|
10
|
-
installGroups: [core]
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Pikku Services (Dependency Injection)
|
|
14
|
-
|
|
15
|
-
## Agent Operating Procedure
|
|
16
|
-
|
|
17
|
-
Use this skill as an execution checklist, not reference material.
|
|
18
|
-
|
|
19
|
-
1. Discover before editing. Prefer OpenCode tools such as `pikku-meta` when available; otherwise run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
|
|
20
|
-
2. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
|
|
21
|
-
3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
|
|
22
|
-
4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
|
|
23
|
-
5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
|
|
24
|
-
|
|
25
|
-
Pikku uses factory functions for dependency injection. Singleton services are created once at startup; wire services are created fresh per request/job/command. See `pikku-concepts` for the core mental model.
|
|
26
|
-
|
|
27
|
-
## Before You Start
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
pikku info functions --verbose # See which services existing functions use
|
|
31
|
-
pikku info tags --verbose # Understand project organization
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## API Reference
|
|
35
|
-
|
|
36
|
-
### `pikkuServices(factory)` — singleton services (created once at startup)
|
|
37
|
-
|
|
38
|
-
```typescript
|
|
39
|
-
import { pikkuServices } from '#pikku'
|
|
40
|
-
import { ConsoleLogger } from '@pikku/core/services'
|
|
41
|
-
import { JoseJWTService } from '@pikku/jose'
|
|
42
|
-
|
|
43
|
-
export const createSingletonServices = pikkuServices(
|
|
44
|
-
async (config, existingServices?) => {
|
|
45
|
-
// config: your CoreConfig object
|
|
46
|
-
// existingServices: optional, for chaining factories
|
|
47
|
-
const logger = new ConsoleLogger()
|
|
48
|
-
const database = new DatabasePool(config.database)
|
|
49
|
-
await database.connect()
|
|
50
|
-
const jwt = new JoseJWTService(
|
|
51
|
-
async () => [{ id: 'my-key', value: config.jwtSecret }],
|
|
52
|
-
logger
|
|
53
|
-
)
|
|
54
|
-
return { config, logger, database, jwt, books: new BookService() }
|
|
55
|
-
}
|
|
56
|
-
)
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### `pikkuWireServices(factory)` — per-request services (fresh per HTTP request, queue job, CLI command, etc.)
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
import { pikkuWireServices } from '#pikku'
|
|
63
|
-
|
|
64
|
-
export const createWireServices = pikkuWireServices(
|
|
65
|
-
async (singletonServices, wire) => {
|
|
66
|
-
// singletonServices: all singleton services
|
|
67
|
-
// wire: transport context (session, channel, etc.)
|
|
68
|
-
// Pikku merges these with singleton services automatically
|
|
69
|
-
return {
|
|
70
|
-
userSession: createUserSessionService(wire),
|
|
71
|
-
dbTransaction: new DatabaseTransaction(singletonServices.database),
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
### Auto-Generated Service Manifest
|
|
78
|
-
|
|
79
|
-
After `npx pikku all`, Pikku generates `.pikku/pikku-services.gen.ts`, a manifest of which services are actually used by wired functions:
|
|
80
|
-
|
|
81
|
-
```typescript
|
|
82
|
-
export const requiredSingletonServices = {
|
|
83
|
-
database: true, // used by getUser, deleteUser
|
|
84
|
-
audit: true, // used by deleteUser
|
|
85
|
-
cache: false, // not used by any wired function
|
|
86
|
-
jwt: true, // used by auth middleware
|
|
87
|
-
} as const
|
|
88
|
-
|
|
89
|
-
export type RequiredSingletonServices = Pick<
|
|
90
|
-
SingletonServices,
|
|
91
|
-
'database' | 'audit' | 'jwt'
|
|
92
|
-
> &
|
|
93
|
-
Partial<Omit<SingletonServices, 'database' | 'audit' | 'jwt'>>
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Usage Patterns
|
|
97
|
-
|
|
98
|
-
### Using Services in Functions
|
|
99
|
-
|
|
100
|
-
**Every service must be declared in `SingletonServices` (or `Services`) in `application-types.d.ts`.** Never access a service via a body-level cast (`services as typeof services & { myService: MyService }`) — that means the type is missing. Add the import and the field to `SingletonServices`, then destructure inline in the function signature. The inspector emits `SERVICES_NOT_DESTRUCTURED` and tree-shaking breaks when the first param is a plain identifier rather than an object pattern. Never `new` a service inside a function — services arrive only via injection.
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
// ✅ Correct — inline destructure, no cast
|
|
104
|
-
const getUser = pikkuFunc({
|
|
105
|
-
title: 'Get User',
|
|
106
|
-
func: async ({ db, logger, jwt }, { userId }) => {
|
|
107
|
-
logger.info('Fetching user', { userId })
|
|
108
|
-
return { user: await db.getUser(userId) }
|
|
109
|
-
},
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
// ❌ Wrong — named param + body cast; inspector warns + tree-shaking breaks
|
|
113
|
-
const getUser = pikkuFunc({
|
|
114
|
-
func: async (services, { userId }) => {
|
|
115
|
-
const { db } = services as typeof services & { db: DbService }
|
|
116
|
-
// ...
|
|
117
|
-
},
|
|
118
|
-
})
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
### Services Are Never Optional Inside a Function
|
|
122
|
-
|
|
123
|
-
**Never write a `if (!service) throw ...` existence guard in a function body.** It is dead code, and it defeats the platform.
|
|
124
|
-
|
|
125
|
-
Optionality lives in exactly one place — `services.ts` / the `SingletonServices` declaration — and it means *"this may not be created"*, not *"this may be missing at call time"*. A service is optional precisely because **nothing destructures it**, and `requireSingletonServices` therefore never creates it. The moment any wired function destructures it, Pikku creates it and guarantees it is there.
|
|
126
|
-
|
|
127
|
-
The types enforce this rather than merely documenting it. The inspector records the services destructured by every wired `func`, `permissions` **and** `middleware`, and emits them as `RequiredSingletonServices`. The generated function types then default their service parameter to:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
export type WiredSingletonServices = RequiredSingletonServices & SingletonServices
|
|
131
|
-
export type WiredServices = RequiredSingletonServices & Services
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
so a service that is `foo?: Foo` in `SingletonServices` arrives as a non-optional `Foo` in every function, permission and middleware that uses it. There is nothing to guard against.
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
// ✅ Correct — destructure and use; creation is guaranteed by the manifest
|
|
138
|
-
const listThreads = pikkuFunc({
|
|
139
|
-
func: async ({ agentRunService }, { threadId }) => {
|
|
140
|
-
return await agentRunService.getThreadMessages(threadId)
|
|
141
|
-
},
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
// ❌ Wrong — unreachable guard; signals a misunderstanding of service wiring
|
|
145
|
-
const listThreads = pikkuFunc({
|
|
146
|
-
func: async ({ agentRunService }, { threadId }) => {
|
|
147
|
-
if (!agentRunService) throw new MissingServiceError('agentRunService')
|
|
148
|
-
return await agentRunService.getThreadMessages(threadId)
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
If a service really is conditional at runtime (e.g. an optional integration a deployment may not configure), that is a **configuration** concern: branch on config, or fail fast at startup in `services.ts` — not per-request in every function.
|
|
154
|
-
|
|
155
|
-
### Dynamic Import Optimization
|
|
156
|
-
|
|
157
|
-
Use the generated manifest to conditionally import heavy dependencies — only the services actually wired get instantiated:
|
|
158
|
-
|
|
159
|
-
```typescript
|
|
160
|
-
import { requiredSingletonServices } from '.pikku/pikku-services.gen.js'
|
|
161
|
-
|
|
162
|
-
const createSingletonServices = pikkuServices(async (config) => {
|
|
163
|
-
const logger = new ConsoleLogger()
|
|
164
|
-
|
|
165
|
-
let jwt: JWTService | undefined
|
|
166
|
-
if (requiredSingletonServices.jwt) {
|
|
167
|
-
const { JoseJWTService } = await import('@pikku/jose')
|
|
168
|
-
jwt = new JoseJWTService(keys, logger)
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
let database: Database | undefined
|
|
172
|
-
if (requiredSingletonServices.database) {
|
|
173
|
-
database = await createDatabase(config.databaseUrl)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return { config, logger, jwt, database }
|
|
177
|
-
})
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### Audit Wire Service
|
|
181
|
-
|
|
182
|
-
`createInvocationAudit` + `createAuditedKysely` add per-request audit buffering that flushes on request close (no-op if `audit` is unconfigured). For the full pattern, no-op behavior, custom-event usage, and Fabric notes, read `references/audit-wire-service.md`.
|
|
183
|
-
|
|
184
|
-
### Built-in Services
|
|
185
|
-
|
|
186
|
-
| Service | Package | Purpose |
|
|
187
|
-
| -------------------------- | ---------------------- | -------------------------------- |
|
|
188
|
-
| `ConsoleLogger` | `@pikku/core/services` | Console-based logging |
|
|
189
|
-
| `JoseJWTService` | `@pikku/jose` | JWT sign/verify via jose |
|
|
190
|
-
| `LocalSecretService` | `@pikku/core/services` | Local development secrets |
|
|
191
|
-
| `LocalVariablesService` | `@pikku/core/services` | Local environment variables |
|
|
192
|
-
| `PinoLogger` | `@pikku/pino` | Structured logging via Pino |
|
|
193
|
-
| `createInvocationAudit` | `@pikku/core/services` | Per-request audit buffer |
|
|
194
|
-
| `createAuditedKysely` | `@pikku/kysely` | Auto-capture DB queries as audit events |
|
|
195
|
-
|
|
196
|
-
## Complete Example
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
// services.ts
|
|
200
|
-
import { pikkuServices, pikkuWireServices } from '#pikku'
|
|
201
|
-
import { ConsoleLogger } from '@pikku/core/services'
|
|
202
|
-
import { JoseJWTService } from '@pikku/jose'
|
|
203
|
-
|
|
204
|
-
// Custom service
|
|
205
|
-
class TodoStore {
|
|
206
|
-
private todos: Map<string, Todo> = new Map()
|
|
207
|
-
async create(title: string, priority: string) {
|
|
208
|
-
const todo = { id: crypto.randomUUID(), title, priority, completed: false }
|
|
209
|
-
this.todos.set(todo.id, todo)
|
|
210
|
-
return todo
|
|
211
|
-
}
|
|
212
|
-
async get(id: string) { return this.todos.get(id) }
|
|
213
|
-
async list() { return [...this.todos.values()] }
|
|
214
|
-
async delete(id: string) { this.todos.delete(id) }
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
export const createSingletonServices = pikkuServices(async (config) => {
|
|
218
|
-
const logger = new ConsoleLogger()
|
|
219
|
-
const jwt = new JoseJWTService(
|
|
220
|
-
async () => [{ id: 'my-key', value: config.jwtSecret }],
|
|
221
|
-
logger
|
|
222
|
-
)
|
|
223
|
-
return {
|
|
224
|
-
config,
|
|
225
|
-
logger,
|
|
226
|
-
jwt,
|
|
227
|
-
secrets: new LocalSecretService(),
|
|
228
|
-
variables: new LocalVariablesService(),
|
|
229
|
-
todoStore: new TodoStore(),
|
|
230
|
-
}
|
|
231
|
-
})
|
|
232
|
-
|
|
233
|
-
export const createWireServices = pikkuWireServices(
|
|
234
|
-
async (singletonServices, wire) => ({
|
|
235
|
-
scopedLogger: new ScopedLogger(wire.session?.initial?.userId),
|
|
236
|
-
})
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
// functions/todos.functions.ts — services are auto-injected
|
|
240
|
-
export const createTodo = pikkuFunc({
|
|
241
|
-
title: 'Create Todo',
|
|
242
|
-
func: async ({ todoStore, logger }, { title, priority }) => {
|
|
243
|
-
const todo = await todoStore.create(title, priority)
|
|
244
|
-
logger.info('Created todo', { id: todo.id })
|
|
245
|
-
return { todo }
|
|
246
|
-
},
|
|
247
|
-
})
|
|
248
|
-
```
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Audit Wire Service
|
|
2
|
-
|
|
3
|
-
`createInvocationAudit` creates a per-request `InvocationAuditLog` that buffers audit events in memory and flushes them as a batch when the function-runner calls `closeWireServices` at the end of the request. If `singletonServices.audit` is not configured (local dev without Fabric), it returns a no-op `DisabledInvocationAudit` — no crash, events are silently dropped.
|
|
4
|
-
|
|
5
|
-
Pair with `createAuditedKysely` to auto-capture every Kysely query as an audit event.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// services.ts
|
|
9
|
-
import { createInvocationAudit } from '@pikku/core/services'
|
|
10
|
-
import { createAuditedKysely } from '@pikku/kysely'
|
|
11
|
-
|
|
12
|
-
export const createWireServices = pikkuWireServices(async (singletonServices, wire) => {
|
|
13
|
-
const audit = createInvocationAudit(singletonServices.audit, wire)
|
|
14
|
-
const kysely = singletonServices.kysely
|
|
15
|
-
? createAuditedKysely(singletonServices.kysely, { audit })
|
|
16
|
-
: undefined
|
|
17
|
-
return { audit, ...(kysely ? { kysely } : {}) }
|
|
18
|
-
})
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The `audit` wire service is typed as `AuditLog` (from `@pikku/core`). Functions that emit custom events use it directly:
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
const deleteUser = pikkuFunc({
|
|
25
|
-
func: async ({ audit }, { userId }) => {
|
|
26
|
-
await audit.audit({ type: 'user.deleted', actor_user_id: userId })
|
|
27
|
-
// ...
|
|
28
|
-
},
|
|
29
|
-
})
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
`closeWireServices` (called automatically by the function-runner) invokes `audit.close()` → `singletonServices.audit.write(batch)` → platform-specific flush (e.g. CF Queue, libsql INSERT). No manual flushing needed.
|
|
33
|
-
|
|
34
|
-
> **Fabric note:** Fabric provisions the audit queue and consumer worker automatically. The audit table schema is in `db/sqlite/0003-audit.sql` (starter-template). Run `pikku fabric validate` to confirm the migration is in place.
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
# pikku-software-archaeology
|
|
2
|
-
|
|
3
|
-
Reverse-engineers an existing repository into a **Product Blueprint**: the product intelligence hidden inside an implementation (domains, entities, commands, queries, events, policies, workflows, invariants, integrations, gaps), extracted as schema-validated JSON that a generator — in our case Pikku — can rebuild from.
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
Existing Repository → pikku-software-archaeology → .knowledge/ blueprint → new Pikku application
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
This is **not** a code indexer or doc generator. It extracts *intent over implementation*: `POST /api/users/:id/status` becomes the command `ActivateUser`; three scattered `if (inv.user_id !== req.user.id)` checks become one `InvoiceOwnerOnly` policy with three `enforcedAt` citations.
|
|
10
|
-
|
|
11
|
-
## Design decision: the AI is the parser
|
|
12
|
-
|
|
13
|
-
There is deliberately **no scanner/AST tooling** in this skill. Static extraction is brittle and per-language (the first prototype's regex scanner broke before it ran once); the analyzing model already reads every language — JS, TS, Ruby, Python, PHP, Go — follows indirection, and understands intent. Determinism lives in the **output contract** instead: fixed file names, schema-validated shapes, sorted unordered collections (sequence-bearing arrays keep their observed order), and stable concept names, all enforced by a dumb JSON validator (`scripts/validate.mjs`). The audit is expensive; that's the trade we chose.
|
|
14
|
-
|
|
15
|
-
## How to run it
|
|
16
|
-
|
|
17
|
-
In Claude Code, from (or pointing at) the target repo:
|
|
18
|
-
|
|
19
|
-
> Use the pikku-software-archaeology skill to extract a product blueprint from /path/to/repo
|
|
20
|
-
|
|
21
|
-
The agent then:
|
|
22
|
-
1. **Surveys** the repo (manifests, entry points, routes, jobs, webhooks, schema, config, TODO/HACK markers) — facts only.
|
|
23
|
-
2. **Excavates the test suite** — `describe`/`it` names become workflow scenarios; assertions confirm policies and upgrade confidence; rules that exist *only* in tests are captured.
|
|
24
|
-
3. **Extracts** through twelve lenses (domains, entities, commands, …) per the pipeline in `SKILL.md`. Large repos fan out subagents per lens and merge.
|
|
25
|
-
4. **Cross-checks and validates**:
|
|
26
|
-
```bash
|
|
27
|
-
node .claude/skills/pikku-software-archaeology/scripts/validate.mjs <repo>/.knowledge
|
|
28
|
-
```
|
|
29
|
-
The validator checks every file against `references/blueprint.schema.json` plus referential integrity across files (commands reference defined domains, api surfaces map to defined commands/queries, events have producers, …).
|
|
30
|
-
5. Writes `blueprint.md`, the human synthesis.
|
|
31
|
-
|
|
32
|
-
Output lands in `<repo>/.knowledge/` — 14 core JSON files + `blueprint.md` (see `SKILL.md` for the full listing). Repos with a frontend and/or non-HTTP consumer channels also get an **optional consumer-surface layer**: `interfaces.json` (every way the product is used — web UI, CLI, MCP server for AI agents, OpenAPI/REST, SDK, realtime, webhooks) plus `frontend.json` / `frontend-routes.json` / `frontend-components.json`. The frontend component inventory's `rebuild` field is the key output: it separates trivially-rebuildable standard components from the **custom-logic** pieces (charts, complex tables, editors) that must be carefully ported. Backend-only repos omit these and the validator does not complain.
|
|
33
|
-
|
|
34
|
-
### Incremental re-analysis
|
|
35
|
-
|
|
36
|
-
Concept names are the stable IDs. On re-run after code changes, re-extract only the affected lens/domain, diff against the existing `.knowledge/`, and leave unrelated entries verbatim. Unordered collections are sorted so diffs stay reviewable; sequence-bearing arrays stay in observed order.
|
|
37
|
-
|
|
38
|
-
## How Pikku consumes the blueprint
|
|
39
|
-
|
|
40
|
-
Full mapping table in `references/pikku-mapping.md`. Summary: entities → Kysely migrations + Zod schemas; commands/queries → `pikkuFunc`s; api surfaces → `wireHTTP`; policies → shared permission functions (collapsing duplicated legacy checks); system workflows → `wireScheduler`/`wireQueueWorker`/`pikkuWorkflowFunc`; integrations → injected services with `wireSecret`/`wireCredential`; test-derived scenarios → `pikkuUserFlow` stories / e2e tests. Humans resolve `migration.json.decisionsNeeded` before any generation starts.
|
|
41
|
-
|
|
42
|
-
## How uncertainty is represented
|
|
43
|
-
|
|
44
|
-
Every extracted concept carries:
|
|
45
|
-
|
|
46
|
-
```json
|
|
47
|
-
{ "evidence": [{ "file": "controllers/invoices.js", "lines": "52", "note": "guard: only drafts editable" }],
|
|
48
|
-
"confidence": "high" }
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
- **high** — the behavior itself is in the cited code/schema/test. Generates directly.
|
|
52
|
-
- **medium** — inferred from converging signals. Generates with a review marker.
|
|
53
|
-
- **low** — plausible reconstruction. Never auto-generated; surfaced for human review.
|
|
54
|
-
|
|
55
|
-
Two further distinctions keep facts and guesses separate:
|
|
56
|
-
- `events[].explicit: false` — the event was *reconstructed* from side-effect clusters (email + status flip), not emitted by the code.
|
|
57
|
-
- Comments/docs vs code: comments describe intent, code describes behavior. Disagreements are recorded as the code's behavior plus a `gaps.json` entry.
|
|
58
|
-
|
|
59
|
-
## Repo layout
|
|
60
|
-
|
|
61
|
-
```
|
|
62
|
-
pikku-software-archaeology/
|
|
63
|
-
├── SKILL.md # skill definition + extraction pipeline
|
|
64
|
-
├── README.md # this file
|
|
65
|
-
├── references/
|
|
66
|
-
│ ├── blueprint.schema.json # the output contract (JSON Schema)
|
|
67
|
-
│ └── pikku-mapping.md # blueprint → Pikku primitives
|
|
68
|
-
└── scripts/
|
|
69
|
-
└── validate.mjs # schema + cross-file validation (node, no deps)
|
|
70
|
-
```
|