@zaip-ai/cli 2.2.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +23 -9
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/agent-adapters.js +25 -9
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-discovery.d.ts +27 -0
- package/dist/services/agent-discovery.d.ts.map +1 -0
- package/dist/services/agent-discovery.js +73 -0
- package/dist/services/agent-discovery.js.map +1 -0
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +153 -24
- package/dist/services/codex-conversation-lifecycle-hook.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +146 -72
- package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
- package/dist/services/codex-rules.d.ts +1 -1
- package/dist/services/codex-rules.d.ts.map +1 -1
- package/dist/services/codex-rules.js +3 -3
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +117 -66
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +56 -6
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/logger.js +1 -1
- package/dist/services/logger.js.map +1 -1
- package/dist/services/logger.test.js +22 -1
- package/dist/services/logger.test.js.map +1 -1
- package/dist/services/runtime-template.test.js +129 -0
- package/dist/services/runtime-template.test.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/.env.example +9 -3
- package/templates/.agents/README-ENG.md +30 -5
- package/templates/.agents/README.md +30 -7
- package/templates/.agents/architecture/software-architecture.md +1 -59
- package/templates/.agents/branding/brandbook.md +3 -0
- package/templates/.agents/config/agents/catalog.yaml +22 -10
- package/templates/.agents/config/agents/discovery.json +319 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +11 -8
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +2 -2
- package/templates/.agents/config/pricing/models.json +9 -5
- package/templates/.agents/config/project.yaml +12 -1
- package/templates/.agents/dashboard/.zaip-managed.json +375 -95
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-CGxeQak4.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-DaSllaJp.js → DashboardHelpDialog-tzS7YxYB.js} +57 -33
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-DEbCi1gP.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-1L7Qw-Gq.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-EInWr641.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-t1Om0Abw.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-B6aZfo5f.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-TPUT2IUt.js → icons-vendor-DiGC-dsJ.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DgTmNHN5.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-Ct48XHGL.js → react-vendor-kPO6yNed.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-Bh1tDfsg.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DQpKX9c1.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +3 -1264
- package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +363 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.dom.test.ts +99 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +62 -6
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/__tests__/app-composition-support.ts +7 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -7
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +151 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +28 -153
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-app-shell.tsx +33 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-cost-facts.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-project-overview.ts +7 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-retry.ts +17 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-setup-route.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-view-actions.ts +66 -0
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +3 -2
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.test.ts +48 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-installation-status.ts +29 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +68 -0
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.test.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/sao-paulo-day-rollover.ts +30 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +2 -5
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +30 -19
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +9 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-task-pagination.ts +77 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-board.ts +397 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +782 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-snapshot-notice.tsx +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperPanelSlot.tsx +16 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +459 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +27 -17
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +62 -186
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorRunDialog.tsx +20 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-hides-calls-that-have-no-collected.test.ts +80 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +455 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +18 -525
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +32 -508
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-export-sources.ts +74 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-actions.ts +19 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-selectors.ts +49 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +115 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test-fixtures.ts +2 -0
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTableBadges.tsx +34 -0
- package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +8 -38
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview-keeps-structure-classes-mutually-exclusive.test.ts +243 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +27 -275
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +70 -247
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +171 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewPanels.tsx +64 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +2 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +6 -2
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +6 -14
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +3 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +2 -0
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +32 -0
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1458 -1458
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1425 -1425
- package/templates/.agents/dashboard/packages/local-runtime/package.json +2 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +7 -3
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1458 -1459
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +53 -8
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +79 -24
- package/templates/.agents/dashboard/packages/local-runtime/src/projection-refresh-diagnostics.ts +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-costs-routes.ts +168 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-dual-reads-manifest-summaries-without-losing.test.ts +344 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-http-contracts.ts +31 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-routes.ts +345 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-read-projections.ts +461 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-route-context.ts +13 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +18 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +19 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +22 -21
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-view-allowlist.test.ts +25 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-trace-routes.ts +64 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +2 -30
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +6 -23
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +2 -330
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +73 -1060
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-first-fold.ts +78 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-projections.ts +561 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-materialize-runs.ts +600 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-agent-dimension.ts +269 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-context.ts +32 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-entity-group.ts +244 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-filtered-dimension.ts +292 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-financial.ts +547 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-model-dimension.ts +360 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-provider-dimension.ts +169 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-summary.ts +475 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-temporal-dimension.ts +132 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-timing.ts +299 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-query-view-page.ts +692 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-counts-every-root-execution-day-returns.test.ts +739 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-does-not-convert-delayed-historical-finalizer.test.ts +706 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-filesystem.ts +748 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-keeps-orphan-telemetry-out-kanban-without.test.ts +710 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-marks-token-cost-telemetry-unavailable-when.test.ts +618 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +755 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuilds-disposable-snapshot-serves-zaip-records.test.ts +276 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-schema.ts +193 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-types.ts +123 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +1 -2805
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +17 -6930
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-base-views.ts +385 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-schema-dashboard-views.ts +412 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +4 -3
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-build.mjs +195 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.test.mjs +2 -7
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-logging.mjs +35 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-navigation.mjs +114 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-paths.mjs +90 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +89 -418
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +22 -12
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
- package/templates/.agents/design/.zaip-managed.json +5 -5
- package/templates/.agents/design/DESIGN.md +2 -186
- package/templates/.agents/design/README.md +12 -2
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/growth/strategy.md +3 -0
- package/templates/.agents/marketing/strategy.md +3 -0
- package/templates/.agents/requirements/autonomous-assurance.md +2 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +1 -1
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +13 -4
- package/templates/.agents/requirements/execution-engine.md +1 -1
- package/templates/.agents/requirements/kanban-dashboard.md +1 -1
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +4 -2
- package/templates/.agents/requirements/software-architecture.md +1 -1
- package/templates/.agents/requirements/strategic-improvements.md +1 -1
- package/templates/.agents/requirements/work-lifecycle.md +3 -3
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/architecture.md +2 -0
- package/templates/.agents/rules/astra-diagnostic.md +1 -1
- package/templates/.agents/rules/autonomy-decision.md +3 -1
- package/templates/.agents/rules/cloud-hostinger-autonomy.md +2 -0
- package/templates/.agents/rules/context.md +2 -1
- package/templates/.agents/rules/core.md +3 -3
- package/templates/.agents/rules/design-system-central-contract.md +17 -0
- package/templates/.agents/rules/evolution.md +3 -1
- package/templates/.agents/rules/frontend-lite.md +3 -1
- package/templates/.agents/rules/local-sqlite-storage.md +2 -2
- package/templates/.agents/rules/meta-mcp.md +3 -1
- package/templates/.agents/rules/model-orchestration.md +1 -1
- package/templates/.agents/rules/run-lifecycle-closure.md +6 -4
- package/templates/.agents/rules/security.md +3 -1
- package/templates/.agents/rules/specialist-routing.md +3 -1
- package/templates/.agents/rules/text-writing-utf8.md +1 -1
- package/templates/.agents/rules/workflow.md +7 -5
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +519 -247
- package/templates/.agents/runtime/checksums.sha256 +6 -6
- package/templates/.agents/runtime/manifest.json +1 -1
- package/templates/.agents/runtime/pnpm-lock.sha256 +1 -1
- package/templates/.agents/runtime/provenance.json +5 -5
- package/templates/.agents/runtime/sbom.cdx.json +1 -1
- package/templates/.agents/sales/playbook.md +3 -0
- package/templates/.agents/skills/zaip-aios/SKILL.md +5 -3
- package/templates/.agents/skills/zaip-skill-adapt-stack/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-api-contracts/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-observability/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-observability/references/signal-design.md +3 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-application-readiness/references/evidence-matrix.md +3 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-architecture-design/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-async-jobs/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/data-access-paths.md +9 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/references/worker-scenario.md +5 -0
- package/templates/.agents/skills/zaip-skill-auth-tenancy/scripts/worker-contract.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-author-skills/references/engineering-skill-index.md +9 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +5 -3
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-backend/references/deployment-environments.md +75 -0
- package/templates/.agents/skills/zaip-skill-backend/references/supabase-migration-contract.md +23 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-cache-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-cloud-engineering/SKILL.md +7 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/SKILL.md +37 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/agents/openai.yaml +6 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workers-static-assets.md +26 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/references/workflow-templates.md +71 -0
- package/templates/.agents/skills/zaip-skill-cloudflare-github-deploy/scripts/cloudflare-github-deploy-contract.test.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-config/SKILL.md +21 -11
- package/templates/.agents/skills/zaip-skill-config/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-container-runtime/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-container-runtime/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-context/SKILL.md +6 -1
- package/templates/.agents/skills/zaip-skill-context/references/prd-spec-task-handoff.md +10 -0
- package/templates/.agents/skills/zaip-skill-context/references/rule-selection.md +20 -0
- package/templates/.agents/skills/zaip-skill-cqrs/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/SKILL.md +18 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/references/audit-contract.md +94 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.mjs +185 -0
- package/templates/.agents/skills/zaip-skill-cybersecurity/scripts/score-audit.test.mjs +101 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-data-modeling/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/manual-mode.md +15 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/references/promotion-example.md +5 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.mjs +145 -0
- package/templates/.agents/skills/zaip-skill-database-migrations/scripts/export-manual-sql.test.mjs +178 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dependency-upgrade/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-deployment-pipeline/references/runtime-shapes.md +3 -0
- package/templates/.agents/skills/zaip-skill-design-system/SKILL.md +20 -9
- package/templates/.agents/skills/zaip-skill-dev-environment/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/references/inventory-contract.md +7 -0
- package/templates/.agents/skills/zaip-skill-dev-environment/scripts/inventory.mjs +77 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-disaster-recovery/references/recovery-scope.md +3 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-execution/references/correction-cycle.md +7 -0
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +1 -5
- package/templates/.agents/skills/zaip-skill-external-integrations/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-external-integrations/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/SKILL.md +44 -0
- package/templates/.agents/skills/zaip-skill-frontend-componentization/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-frontend-data-flows/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/SKILL.md +36 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/cloudflare-pages.md +33 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/github.md +63 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/hostinger-vps.md +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/references/npm.md +30 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/check-skill.mjs +55 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs +61 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.test.mjs +128 -0
- package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-ssh.integration.test.mjs +106 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +43 -76
- package/templates/.agents/skills/zaip-skill-github-deploy/references/deployment-workflow.md +131 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/github-release-workflow-template.md +31 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-gate-matrix.md +24 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-identity.md +44 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/references/release-notes.md +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.mjs +389 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/consumer-release-preparation.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +25 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness-api.test.mjs +134 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.mjs +98 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-readiness.test.mjs +25 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.mjs +159 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/install-github-readiness-workflow.test.mjs +160 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +149 -12
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +64 -5
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/release-notes-coverage.test.mjs +126 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.mjs +78 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/resolve-release-identity.test.mjs +51 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.mjs +184 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/validate-release-notes.test.mjs +109 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +18 -10
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +3 -4
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/aws-cli-terraform.md +62 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/guia-iniciante-hostinger-vps.md +183 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/references/scaffold-contract.md +9 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/helpers.test.mjs +121 -0
- package/templates/.agents/skills/zaip-skill-module-scaffold/scripts/scaffold.mjs +169 -0
- package/templates/.agents/skills/zaip-skill-move-prd/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-move-spec/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-performance-engineering/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-performance-engineering/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +26 -9
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +39 -13
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +1 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/SKILL.md +66 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-refactor-landing-page/references/behavioral-dry-run.md +23 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +40 -1
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +98 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +3 -3
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +2 -0
- package/templates/.agents/skills/zaip-skill-setup/SKILL.md +19 -21
- package/templates/.agents/skills/zaip-skill-setup/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-storage-uploads/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-storage-uploads/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-systematic-debugging/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-task/SKILL.md +16 -7
- package/templates/.agents/skills/zaip-skill-task/references/commit-policy.md +25 -0
- package/templates/.agents/skills/zaip-skill-test-data/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-test-data/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-test-data/scripts/generate.mjs +72 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/SKILL.md +15 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-testing-strategy/references/example-map.md +3 -0
- package/templates/.agents/skills/zaip-skill-website-readiness/SKILL.md +8 -0
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +2 -1
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +5 -3
- package/templates/scripts/validate-cloud-hostinger-contract.mjs +34 -0
- package/templates/template-manifest.json +955 -211
- package/templates/.agents/branding/.gitkeep +0 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-snUCQYTC.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-BPtVUGgs.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-GgzpZ_PY.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BCvZFMEf.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-_MEktQNM.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-BDe4_Ubl.js +0 -1
- package/templates/.agents/growth/.gitkeep +0 -0
- package/templates/.agents/marketing/.gitkeep +0 -0
- package/templates/.agents/sales/.gitkeep +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: zaip-skill-github-actions-setup
|
|
3
|
+
description: Configure GitHub Actions end to end for npm publishing, Cloudflare Pages frontend or Hostinger VPS backend, guiding credential setup and verifying access and deployments. Use for CI/CD onboarding or broken deployment credentials, not a routine GitHub push.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Configurar GitHub Actions com o usuário
|
|
7
|
+
|
|
8
|
+
Entregue workflows específicos do projeto, um guia preenchido com nomes exatos, testes executados e evidências. Acompanhe correções até funcionar ou até uma dependência concreta impedir o próximo passo; não encerre apenas entregando YAML.
|
|
9
|
+
|
|
10
|
+
## Descoberta e autorização
|
|
11
|
+
|
|
12
|
+
1. Leia configuração, remotes, workflows, manifests, lockfile e scripts de build/deploy existentes. Identifique repositório, pacote/app, diretório, provedor, ambiente, branch, runner e estratégia de release. Reutilize nomes já válidos.
|
|
13
|
+
2. Pergunte somente o que falta: destinos desejados (npm, Pages, VPS, Supabase migration ou combinação), conta/projeto, ambiente e acesso administrativo. Faça poucas perguntas por vez. Não peça credenciais de provedores que não serão usados. Para migrations, explique antes que uma beta Supabase persistente pode gerar custo e obtenha confirmação explícita antes de criar branch hospedada, integração, GitHub App, secret ou workflow.
|
|
14
|
+
3. Distinga configuração local, cadastro de credenciais, push, execução de verificação e deploy real. Reutilize autorização já dada. Prepare arquivos e comandos revisáveis antes de pedir autorização ainda ausente para publicar, alterar servidor ou promover produção.
|
|
15
|
+
4. Nunca peça tokens, senhas, chaves privadas, OTP ou recovery codes no chat, screenshots ou registros. Peça cadastro diretamente no destino indicado e confirmação apenas de nome/escopo. Credencial local já existente segue [local-credentials](../zaip-skill-local-credentials/SKILL.md), sem busca global.
|
|
16
|
+
5. Leia [contrato de secrets e testes](references/github.md) e somente as trilhas escolhidas: [npm](references/npm.md), [Cloudflare Pages](references/cloudflare-pages.md), [Hostinger VPS](references/hostinger-vps.md). Consulte as fontes oficiais ali vinculadas antes de configurar: telas, requisitos, permissões e versões podem mudar.
|
|
17
|
+
|
|
18
|
+
## Implementação guiada
|
|
19
|
+
|
|
20
|
+
6. Produza uma tabela preenchida: nome exato, secret ou variable, origem, escopo GitHub, job consumidor e teste. Use os nomes de referência em projetos novos; nomes existentes exigem mapeamento explícito no guia, scripts e YAML. A pessoa não deve adivinhar o que preencher.
|
|
21
|
+
7. Explique cada cadastro na ordem das telas, valor esperado sem exibi-lo, onde salvar e como confirmar. GitHub Environment por ambiente é preferível quando disponível; repository secrets são alternativa explícita. IDs/configuração pública ficam em variables. Secrets de runtime ficam no servidor/secret manager; nada secreto entra em bundle frontend.
|
|
22
|
+
8. Crie apenas os workflows selecionados no repositório do usuário e um guia operacional sem segredos. Separe verificação de publicação; modo verificar não pode subir pacote, criar deployment, reiniciar serviço ou mudar dados. Primeiro valide YAML, comandos, build e empacotamento locais.
|
|
23
|
+
9. Integre ao stack: npm publica o tarball validado; Pages recebe o output real; VPS recebe artefato identificado por SHA e segue o runtime existente. Migrations usam o repositório central e `deploy.database.branch: beta`, com GitHub Integration como aplicador hospedado; o workflow nunca executa SQL direto em produção. Fixe actions por SHA verificado e ferramentas por versão compatível. Não entregue placeholders executáveis como configuração concluída.
|
|
24
|
+
10. Use [deployment-pipeline](../zaip-skill-deployment-pipeline/SKILL.md) para entrega; [cloudflare-github-deploy](../zaip-skill-cloudflare-github-deploy/SKILL.md) para Pages; [github-deploy](../zaip-skill-github-deploy/SKILL.md) somente para publicação GitHub autorizada. Provisionamento VPS/DNS é outra operação: [hostinger-cloudflare-terraform](../zaip-skill-hostinger-cloudflare-terraform/SKILL.md) aplica-se apenas quando solicitado.
|
|
25
|
+
|
|
26
|
+
## Verificação até o destino
|
|
27
|
+
|
|
28
|
+
11. Confira nomes e escopos via UI ou `gh secret list` / `gh variable list`, sem tentar recuperar valores. Isso comprova cadastro, não funcionamento.
|
|
29
|
+
12. Execute o job de verificação no GitHub com os mesmos secrets, environment e destino do deploy. Investigue logs sanitizados; corrija nome, escopo, permissão, expiração, trust ou conectividade e repita o teste que falhou.
|
|
30
|
+
13. Faça deploy de teste somente no destino autorizado. npm requer versão nova real e canal explícito; Pages usa preview explícito; VPS usa staging/serviço escolhido. Ambiente indisponível não autoriza testar produção.
|
|
31
|
+
14. Aguarde o run e verifique provedor e consumidor. Registre workflow/run URL, SHA, ambiente, artefato/versão, smoke e limites. Não confunda token ativo, SSH conectado, dry-run ou HTTP 200 genérico com publicação funcional.
|
|
32
|
+
15. Termine com estados separados: configurado, autenticação/acesso verificados, deploy verificado, pendências e próximo passo exato. Se depender do usuário, indique a tela/campo pendente; retome dali sem refazer cadastros concluídos.
|
|
33
|
+
|
|
34
|
+
## Portabilidade
|
|
35
|
+
|
|
36
|
+
Esta skill e seus recursos podem acompanhar o instalador npm. Sua instalação não cria workflows ativos, secrets, contas, recursos nem solicita credenciais. Workflows são gerados sob demanda para o projeto selecionado. O workflow npm exclusivo do mantenedor ZAIP-AIOS permanece fora do pacote; esta skill não recupera a antiga publicação npm local.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Configurar GitHub Actions"
|
|
3
|
+
short_description: "Guie credenciais e testes de npm, Pages e VPS"
|
|
4
|
+
default_prompt: "Use $zaip-skill-github-actions-setup para configurar meu deploy pelo GitHub Actions, orientar credenciais e verificar o resultado ponta a ponta."
|
package/templates/.agents/skills/zaip-skill-github-actions-setup/references/cloudflare-pages.md
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Frontend no Cloudflare Pages
|
|
2
|
+
|
|
3
|
+
## Conta, projeto e token
|
|
4
|
+
|
|
5
|
+
1. Identifique app, lockfile, diretório, build e output real. Confirme Pages; Workers segue a skill especializada. Verifique dono atual do deploy: Git integration ou Actions; não ative ambos para o mesmo evento.
|
|
6
|
+
2. Cloudflare Dashboard → Workers & Pages → projeto: confirme nome, conta e production branch. Projeto novo: Create application → Pages → Direct Upload, conforme UI atual; criação externa depende de autorização.
|
|
7
|
+
3. Account ID da conta/painel vai em variable **CLOUDFLARE_ACCOUNT_ID**; nome do projeto em **CLOUDFLARE_PAGES_PROJECT**. Esses valores não são tokens.
|
|
8
|
+
4. Perfil → API Tokens → Create Token → Custom token: Account → Cloudflare Pages → Edit; limite Account Resources à conta alvo. Defina validade/rotação. Não conceda DNS Edit, Global API Key ou todas as contas por conveniência.
|
|
9
|
+
5. Token de usuário vai diretamente para GitHub secret **CLOUDFLARE_API_TOKEN**, environment **pages-preview**. Token existente de conta pode usar endpoint diferente; preserve o tipo e adapte o probe, sem substituir automaticamente.
|
|
10
|
+
6. **CLOUDFLARE_PAGES_BRANCH** é preview explícito, diferente da production branch. Verifique pela API/configuração antes do upload. Produção tem job/environment e autorização próprios.
|
|
11
|
+
|
|
12
|
+
## Testar dentro do Actions
|
|
13
|
+
|
|
14
|
+
O helper [verify-cloudflare.mjs](../scripts/verify-cloudflare.mjs) faz somente GET para token de usuário: verifica estado ativo e leitura do projeto exato. Saída contém etapas/resultados sanitizados. Conta/projeto inválidos falham antes da rede. Use Node >=22.14 e este passo dentro de job com o mesmo environment do deploy:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
- name: Verify Cloudflare access
|
|
18
|
+
env:
|
|
19
|
+
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
20
|
+
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
|
|
21
|
+
CLOUDFLARE_PAGES_PROJECT: ${{ vars.CLOUDFLARE_PAGES_PROJECT }}
|
|
22
|
+
run: node .agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Se a skill instalada não for versionada, copie o helper revisado para script project-owned e ajuste o caminho no workflow. GET aprovado comprova leitura, **não** upload. Não imprima token, curl verbose ou resposta integral que possa conter configuração sensível. O helper recusa redirects e oculta corpos/erros remotos. 401/403 pede correção de validade/conta/permissão; 404 pede conferir projeto/conta, não ampliar token.
|
|
26
|
+
|
|
27
|
+
## Entrega e smoke
|
|
28
|
+
|
|
29
|
+
Use Wrangler fixado e instalado pelo lockfile, pages deploy do output verificado, --project-name e --branch explícitos. Passe env validado e argumentos citados. Build ocorre antes de disponibilizar token. VITE_*/NEXT_PUBLIC_* são públicos no bundle: nenhum segredo ali. Secrets de Functions/runtime ficam no store Cloudflare apropriado, separados do token de upload.
|
|
30
|
+
|
|
31
|
+
Com autorização, envie preview e capture deployment ID/URL; confira conta, projeto, branch, SHA e estado na API. GET na URL exata deve validar conteúdo identificável da aplicação, rota principal, assets e navegação/fallback aplicáveis. HTTP 200 de página padrão/login não prova frontend correto. Corrija build/output, token somente leitura, branch indevida ou SPA e reteste. Registre URL/SHA sem configuração sensível.
|
|
32
|
+
|
|
33
|
+
Fontes: [CI Direct Upload](https://developers.cloudflare.com/pages/how-to/use-direct-upload-with-continuous-integration/), [Consultar projeto](https://developers.cloudflare.com/api/resources/pages/subresources/projects/methods/get/), [Token de usuário](https://developers.cloudflare.com/api/resources/user/subresources/tokens/), [Token de conta](https://developers.cloudflare.com/api/resources/accounts/subresources/tokens/).
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# GitHub: cadastro, contrato e execução
|
|
2
|
+
|
|
3
|
+
## Preencha primeiro o contrato do projeto
|
|
4
|
+
|
|
5
|
+
Informe OWNER/REPO verificado, branch autorizada, environment, filename, diretório da aplicação, comando de build, alvo de teste e alvo de produção. Campos deste guia devem ser resolvidos, nunca usados como defaults de produção.
|
|
6
|
+
|
|
7
|
+
Padrão para projetos novos; preserve nomes existentes com mapeamento explícito:
|
|
8
|
+
|
|
9
|
+
| Destino / environment sugerido | Nome exato | Tipo | Origem / consumidor |
|
|
10
|
+
| --- | --- | --- | --- |
|
|
11
|
+
| npm / npm | Nenhum token no modo OIDC | Trust no npm | Identidade GitHub do job publicador |
|
|
12
|
+
| npm / npm | NPM_TOKEN | Secret, só fallback | Token granular, mapeado a NODE_AUTH_TOKEN só no passo npm |
|
|
13
|
+
| Pages / pages-preview | CLOUDFLARE_API_TOKEN | Secret | Token de usuário, job Pages |
|
|
14
|
+
| Pages / pages-preview | CLOUDFLARE_ACCOUNT_ID | Variable | Conta Cloudflare, job/probe Pages |
|
|
15
|
+
| Pages / pages-preview | CLOUDFLARE_PAGES_PROJECT | Variable | Nome exato do projeto |
|
|
16
|
+
| Pages / pages-preview | CLOUDFLARE_PAGES_BRANCH | Variable | Preview diferente da production branch |
|
|
17
|
+
| VPS / vps-staging | VPS_SSH_PRIVATE_KEY | Secret | Chave exclusiva de deploy, job SSH |
|
|
18
|
+
| VPS / vps-staging | VPS_KNOWN_HOSTS | Variable | Chave pública do host verificada fora da conexão |
|
|
19
|
+
| VPS / vps-staging | VPS_HOST | Variable | IP/hostname real |
|
|
20
|
+
| VPS / vps-staging | VPS_PORT | Variable | Porta SSH real |
|
|
21
|
+
| VPS / vps-staging | VPS_USER | Variable | Usuário de deploy |
|
|
22
|
+
| VPS / vps-staging | VPS_DEPLOY_PATH | Variable | Diretório de releases |
|
|
23
|
+
| VPS / vps-staging | VPS_SERVICE | Variable | Serviço real |
|
|
24
|
+
| VPS / vps-staging | VPS_HEALTH_URL | Variable | Endpoint HTTPS da API |
|
|
25
|
+
|
|
26
|
+
Host pode ser secret por privacidade; ajuste o contexto em todo YAML. Nenhum GitHub PAT é necessário por padrão: GITHUB_TOKEN é fornecido pelo Actions. Não solicite senha npm/Cloudflare/Hostinger nem token Hostinger para deploy SSH.
|
|
27
|
+
|
|
28
|
+
## Cadastro pela interface
|
|
29
|
+
|
|
30
|
+
1. Abra o repositório correto → Settings. Confirme permissão de administração do environment; se faltar, peça o cadastro ao administrador.
|
|
31
|
+
2. Em Environments, crie/selecione o nome exato do guia. Configure branches/tags permitidos e proteção de produção disponível no plano. O job declara exatamente esse environment.
|
|
32
|
+
3. Environment secrets → Add secret: copie o nome do guia e cole o valor diretamente do provedor no GitHub. Preserve quebras de linha da chave privada. Salve; não cole na conversa.
|
|
33
|
+
4. Environment variables → Add variable: cadastre cada configuração não secreta pelo nome exato.
|
|
34
|
+
5. Se environments não estiverem disponíveis, escolha repository scope conscientemente: Settings → Secrets and variables → Actions → Secrets → New repository secret; aba Variables → New repository variable. Não suponha proteção de ambiente inexistente.
|
|
35
|
+
6. Confirme somente os nomes. Secrets homônimos em environment/repository/organization podem se sobrepor; investigue o escopo que o job recebe.
|
|
36
|
+
|
|
37
|
+
Alternativa no terminal **do usuário**, com entrada interativa protegida:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
gh secret set CLOUDFLARE_API_TOKEN --repo OWNER/REPO --env pages-preview
|
|
41
|
+
gh secret list --repo OWNER/REPO --env pages-preview
|
|
42
|
+
gh variable list --repo OWNER/REPO --env pages-preview
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Substitua OWNER/REPO e ambiente pelos valores resolvidos. Chave multilinha: prefira UI. Não use --body com valor secreto, echo, leitura de clipboard pelo agente, arquivo versionado ou logs de debug. Arquivo temporário, se necessário, é privado, fora do repo e removido após envio seguro. Não solicite códigos de 2FA; reaproveite sessão autenticada.
|
|
46
|
+
|
|
47
|
+
## Contrato dos workflows produzidos
|
|
48
|
+
|
|
49
|
+
- Configure workflow_dispatch para verificação sem mutação; job/arquivo separado ou input tipado com verify por padrão. Publicação recebe ambiente/canal/ref delimitados e depende das validações.
|
|
50
|
+
- Restrinja repositório e refs, environment, permissions, timeout e concorrência por destino; produção exige promoção autorizada. Nunca exponha secrets a código de fork/PR não confiável, especialmente pull_request_target com checkout do PR.
|
|
51
|
+
- Passe dados de evento/input/variables via env, valide allowlists e cite argumentos. Não interpole esses valores diretamente no shell. SSH usa shell remoto: valide parâmetros antes de compor o comando remoto.
|
|
52
|
+
- Credenciais só no passo necessário. Instalação/build e smoke não herdam token de escrita. Não use set -x, printenv, dumps de contexto, curl -v ou upload de .npmrc/.ssh/.env.
|
|
53
|
+
- Instale pelo lockfile e vincule o artefato ao SHA. Fixe actions por SHA confirmado no repositório oficial; nunca invente SHA.
|
|
54
|
+
- workflow_dispatch exige workflow presente na default branch. Se for produção, não faça merge implícito: prepare a mudança e obtenha autorização necessária. A ref selecionada respeita filtro do ambiente.
|
|
55
|
+
- Eventos gerados com GITHUB_TOKEN podem não disparar outro workflow. Avalie o evento real; workflow_dispatch é opção explícita sem PAT amplo automático.
|
|
56
|
+
|
|
57
|
+
## Acompanhar e corrigir
|
|
58
|
+
|
|
59
|
+
Com autorização aplicável, execute `gh workflow run FILENAME --repo OWNER/REPO --ref BRANCH` com inputs definidos no workflow. Identifique o run por workflow, event, ref, horário e SHA; não escolha o último run concorrente. Use `gh run watch RUN_ID --repo OWNER/REPO --exit-status`.
|
|
60
|
+
|
|
61
|
+
Secret ausente pede checagem de nome/escopo, environment, disponibilidade em fork/Dependabot/reusable workflow e proteções pendentes. Não regenere credencial válida antes disso. Segredo exposto em log exige revogação/rotação e tratamento no provedor; nunca copie o valor ao relatório.
|
|
62
|
+
|
|
63
|
+
Fontes: [Secrets](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets), [Environments](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/manage-environments), [Triggers](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/trigger-a-workflow).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Backend em Hostinger VPS existente
|
|
2
|
+
|
|
3
|
+
## Descoberta e contrato
|
|
4
|
+
|
|
5
|
+
Inspecione runtime (systemd, Docker Compose, outro), artefato, OS/arquitetura, proxy/TLS, health endpoint, diretório e rollback. Não imponha Docker, Terraform ou dois VPS a servidor existente. SSH não requer token da API Hostinger. Provisionamento, DNS e migrations precisam do escopo correspondente.
|
|
6
|
+
|
|
7
|
+
Preencha cada campo: VPS_HOST, VPS_PORT, VPS_USER, VPS_DEPLOY_PATH, VPS_SERVICE, VPS_HEALTH_URL, VPS_KNOWN_HOSTS e secret VPS_SSH_PRIVATE_KEY; environment sugerido vps-staging. Não assuma porta 22, root, serviço nem produção.
|
|
8
|
+
|
|
9
|
+
## Obter acesso e cadastrar
|
|
10
|
+
|
|
11
|
+
1. hPanel → VPS → Manage → Overview: confirme IP e SSH; use porta efetiva. Web Console fornece primeiro acesso. Senha root fica com usuário, não no GitHub.
|
|
12
|
+
2. Identifique/crie quando autorizado usuário de deploy com acesso só à pasta/comandos necessários. Evite sudo irrestrito; grupo docker equivale a privilégio elevado e precisa ser justificado.
|
|
13
|
+
3. Na máquina confiável do usuário, fora do repo, gere chave dedicada: `ssh-keygen -t ed25519 -C github-actions-deploy`; escolha filename novo, sem sobrescrever chave existente. Comando solicita destino/passphrase. A receita abaixo usa chave de automação sem passphrase, restrita no servidor e protegida no GitHub. Se a política exigir passphrase, implemente/teste ssh-agent e secret adicional antes de continuar; não retire proteção de chave pessoal.
|
|
14
|
+
4. Pelo console/conexão confiável, acrescente somente a chave **pública** .pub ao authorized_keys do usuário de deploy, preservando entradas. Confirme ownership do usuário, .ssh 700 e authorized_keys 600. Restrinja forwarding/comandos quando compatível com upload; teste sem bloquear administrador.
|
|
15
|
+
5. Cole chave **privada completa**, com cabeçalho/rodapé/quebras de linha, diretamente no GitHub → vps-staging → secret VPS_SSH_PRIVATE_KEY. Não confunda .pub com privada; não salve em .env/repositório.
|
|
16
|
+
6. Pelo Web Console confiável, obtenha chave pública do host e fingerprint (exemplo `ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub`). Monte VPS_KNOWN_HOSTS: `HOST ssh-ed25519 PUBLIC_KEY` na porta padrão ou `[HOST]:PORT ssh-ed25519 PUBLIC_KEY` em porta customizada, com host e chave verificados.
|
|
17
|
+
7. ssh-keyscan sozinho não autentica o servidor. Se coletar por ele, compare fingerprint ao console antes de salvar. Divergência bloqueia conexão; nunca use StrictHostKeyChecking=no como correção.
|
|
18
|
+
8. Cadastre demais variables conforme destinos existentes. Secrets da aplicação ficam em arquivo/store protegido no VPS; workflow recebe só credencial de deploy. Imagem privada pode exigir leitura do registry, separadamente e apenas se necessária.
|
|
19
|
+
|
|
20
|
+
## Teste sem alterar aplicação
|
|
21
|
+
|
|
22
|
+
Gere job Linux com timeout, mesmo environment do deploy e Bash. Mapear env não é interpolar valores no script. Complete o fragmento com permissions, refs e versões do contrato GitHub:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
set -euo pipefail
|
|
26
|
+
[[ "$VPS_HOST" =~ ^[A-Za-z0-9][A-Za-z0-9.-]*$ ]] || exit 2
|
|
27
|
+
[[ "$VPS_PORT" =~ ^[0-9]{1,5}$ ]] || exit 2
|
|
28
|
+
(( 10#$VPS_PORT >= 1 && 10#$VPS_PORT <= 65535 )) || exit 2
|
|
29
|
+
[[ "$VPS_USER" =~ ^[a-z_][a-z0-9_-]*$ ]] || exit 2
|
|
30
|
+
test -n "$VPS_SSH_PRIVATE_KEY"
|
|
31
|
+
test -n "$VPS_KNOWN_HOSTS"
|
|
32
|
+
umask 077
|
|
33
|
+
ssh_tmp="$(mktemp -d)"
|
|
34
|
+
trap 'rm -f -- "$ssh_tmp/key" "$ssh_tmp/known_hosts"; rmdir -- "$ssh_tmp"' EXIT
|
|
35
|
+
printf '%s\n' "$VPS_SSH_PRIVATE_KEY" > "$ssh_tmp/key"
|
|
36
|
+
printf '%s\n' "$VPS_KNOWN_HOSTS" > "$ssh_tmp/known_hosts"
|
|
37
|
+
unset VPS_SSH_PRIVATE_KEY
|
|
38
|
+
ssh -F /dev/null -i "$ssh_tmp/key" -p "$VPS_PORT" \
|
|
39
|
+
-o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes \
|
|
40
|
+
-o ConnectTimeout=15 -o ConnectionAttempts=1 \
|
|
41
|
+
-o UserKnownHostsFile="$ssh_tmp/known_hosts" \
|
|
42
|
+
"$VPS_USER@$VPS_HOST" 'true'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Exemplo aceita hostname/IPv4; adapte/teste se precisar IPv6. Depois acrescente comandos read-only do runtime: identidade esperada, pasta, espaço e estado do serviço. Valide paths/service contra contrato restrito antes do shell remoto; aspas locais não bastam para SSH. Não faça restart, mkdir/upload, migrations ou docker pull no modo verify.
|
|
46
|
+
|
|
47
|
+
Runner sem conectividade: cheque DNS/porta/firewall e política de rede; não libere SSH para toda Internet automaticamente. Use solução aprovada de rede privada/runner adequado. Permission denied pede usuário, par de chaves e permissões. Host key mismatch exige validação pelo console.
|
|
48
|
+
|
|
49
|
+
## Deploy e retorno
|
|
50
|
+
|
|
51
|
+
Prepare artefato identificado por SHA/checksum em CI. Implemente upload para release nova, integridade remota, ativação atômica compatível e restart/reload só do serviço permitido. Não use git pull irrestrito ou rsync --delete sobre dados/secrets. Backup/migrations seguem contrato de dados; rollback de código não desfaz banco.
|
|
52
|
+
|
|
53
|
+
Teste no staging/serviço autorizado. Confirme readiness local e HTTPS em VPS_HEALTH_URL, identidade/versão implantada e resposta esperada da API. Não exponha logs sensíveis. Se falhar, capture diagnóstico sanitizado, restaure release anterior pelo procedimento preparado quando seguro/autorizado e confirme health. Registre SHA, artefato, serviço, run e resultado; SSH conectado não é backend implantado.
|
|
54
|
+
|
|
55
|
+
Fonte: [SSH e Web Console Hostinger](https://www.hostinger.com/support/5723772-how-to-connect-to-your-vps-via-ssh-at-hostinger/). Consulte documentação do runtime/proxy observado antes de escrever ativação.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# npm: trust, publicação e prova
|
|
2
|
+
|
|
3
|
+
Resolva pacote, registry, visibility, diretório, versão SemVer, canal, branch e filename. Leia package.json, publishConfig, files e hooks. Não imponha a versão do framework a consumidores. No mantenedor ZAIP-AIOS reutilize seu workflow exclusivo, sem outro publicador.
|
|
4
|
+
|
|
5
|
+
## Trusted Publishing, opção preferida
|
|
6
|
+
|
|
7
|
+
1. Usuário entra no npm como mantenedor do pacote → página do pacote → Settings → Trusted Publisher → GitHub Actions.
|
|
8
|
+
2. Entregue valores exatos: organization/user, repository sem owner, filename (exemplo publish-npm.yml, **sem** .github/workflows/), environment igual ao job.
|
|
9
|
+
3. Allowed actions deve corresponder ao workflow: publicação direta permite npm publish; staged publishing tem aprovação própria e não equivale a pacote publicado.
|
|
10
|
+
4. Use runner GitHub hospedado, contents: read e id-token: write só no job publicador, com environment/refs protegidos. Confira requisitos atuais: baseline Node >=22.14 e npm >=11.5.1. Fixe versões suportadas, sem depender silenciosamente do npm do runner.
|
|
11
|
+
5. OIDC não requer NPM_TOKEN/NODE_AUTH_TOKEN. Dependências privadas podem exigir credencial de leitura separada, só no install.
|
|
12
|
+
6. Pacote ainda inexistente: confira bootstrap suportado atualmente. Não prometa Settings de pacote que não existe. Prepare primeira publicação pelo Actions com fallback granular autorizado quando necessário; depois configure trust e remova/revogue o token temporário. Nunca publique pacote de teste arbitrário nem execute npm publish local.
|
|
13
|
+
|
|
14
|
+
## Fallback granular, quando necessário
|
|
15
|
+
|
|
16
|
+
Explique por que OIDC não atende ao runner/registry/pacote. npm → avatar → Access Tokens → Generate New Token; nome para repo/ambiente, Read and write somente no pacote/scope selecionado, validade mínima adequada, sem acesso organizacional extra. Verifique Bypass 2FA exigido para publicação não interativa e política do pacote; não remova 2FA da conta. Usuário cola token diretamente no GitHub secret **NPM_TOKEN**, environment **npm**, nunca na conversa.
|
|
17
|
+
|
|
18
|
+
Configure registry HTTPS correto e mapeie secrets.NPM_TOKEN para NODE_AUTH_TOKEN somente no passo necessário. .npmrc contém referência literal à variável, nunca o valor. Planeje rotação: confirme substituto antes de revogar anterior.
|
|
19
|
+
|
|
20
|
+
## Qualificar, testar e observar
|
|
21
|
+
|
|
22
|
+
- Build/testes, npm pack --dry-run, inspeção de arquivos, pack real, checksum e instalação/smoke do tarball limpo. Exclua .env, SSH, tokens e arquivos privados.
|
|
23
|
+
- Build sem credencial de escrita. Revise lifecycle scripts; prefira publicar tarball preparado com --ignore-scripts quando compatível.
|
|
24
|
+
- Combine pacote aprovado, versão inédita e canal explícito antes do teste real. Publicação npm é persistente mesmo com tag de teste. Não altere latest para diagnosticar.
|
|
25
|
+
- O job confere tag/ref, manifesto, SHA e canal e publica o mesmo tarball validado. Use provenance quando os requisitos de pacote/repositório permitirem.
|
|
26
|
+
- OIDC: id-token/trust presente ou dry-run não prova permissão de publish; npm whoami não valida esse grant. Fallback: teste autenticado read-only suportado prova somente autenticação; whoami pode exigir 2FA/política e não decide isoladamente validade de publicação.
|
|
27
|
+
- Prova final: run bem-sucedido, pacote@versão no registry, dist-tag esperado, integridade igual ao tarball e instalação/smoke da versão exata. Staged aguardando aprovação permanece pendente.
|
|
28
|
+
- 401/403: confira registry, validade, escopo/2FA e trust (owner, repo, filename, environment, allowed actions). Versão existente não é erro de token; não sobrescreva. Retry só considera recuperado após verificar integridade e canal.
|
|
29
|
+
|
|
30
|
+
Fontes: [Trusted publishers](https://docs.npmjs.com/trusted-publishers/), [Criar token](https://docs.npmjs.com/creating-and-viewing-access-tokens/), [Publicar](https://docs.npmjs.com/cli/v11/commands/npm-publish/), [Provenance](https://docs.npmjs.com/generating-provenance-statements/).
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
4
|
+
import { dirname, relative, resolve } from "node:path";
|
|
5
|
+
import { parseDocument } from "../../zaip-skill-github-deploy/scripts/yaml-parser.mjs";
|
|
6
|
+
|
|
7
|
+
const skill = resolve(import.meta.dirname, "..");
|
|
8
|
+
const root = resolve(skill, "../../..");
|
|
9
|
+
const read = (file) => readFileSync(file, "utf8");
|
|
10
|
+
function yaml(source) {
|
|
11
|
+
const doc = parseDocument(source, { strict: true, uniqueKeys: true });
|
|
12
|
+
assert.equal(doc.errors.length, 0);
|
|
13
|
+
return doc.toJS();
|
|
14
|
+
}
|
|
15
|
+
const source = read(resolve(skill, "SKILL.md"));
|
|
16
|
+
const meta = yaml(source.match(/^---\r?\n([\s\S]*?)\r?\n---/)[1]);
|
|
17
|
+
assert.deepEqual(Object.keys(meta).sort(), ["description", "name"]);
|
|
18
|
+
assert.equal(meta.name, "zaip-skill-github-actions-setup");
|
|
19
|
+
assert.ok(source.split(/\r?\n/).length <= 120);
|
|
20
|
+
const ui = yaml(read(resolve(skill, "agents/openai.yaml"))).interface;
|
|
21
|
+
assert.ok(ui.default_prompt.includes("$" + meta.name));
|
|
22
|
+
assert.ok(ui.short_description.length >= 25 && ui.short_description.length <= 64);
|
|
23
|
+
|
|
24
|
+
const lock = yaml(read(resolve(root, ".agents/config/framework.lock.yaml")));
|
|
25
|
+
const files = readdirSync(skill, { recursive: true, withFileTypes: true }).filter((e) =>
|
|
26
|
+
e.isFile(),
|
|
27
|
+
);
|
|
28
|
+
for (const entry of files) {
|
|
29
|
+
const file = resolve(entry.parentPath, entry.name);
|
|
30
|
+
const path = relative(root, file).replaceAll("\\", "/");
|
|
31
|
+
const text = read(file);
|
|
32
|
+
const hash = createHash("sha256").update(text.replaceAll("\r\n", "\n")).digest("hex");
|
|
33
|
+
assert.equal(lock.managed_files[path], hash, "managed content differs: " + path);
|
|
34
|
+
if (!path.endsWith(".md")) continue;
|
|
35
|
+
for (const match of text.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) {
|
|
36
|
+
if (/^https:\/\//.test(match[1])) continue;
|
|
37
|
+
assert.ok(
|
|
38
|
+
existsSync(resolve(dirname(file), match[1].split("#")[0])),
|
|
39
|
+
"missing local resource: " + match[1],
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const page = read(resolve(skill, "references/cloudflare-pages.md"));
|
|
44
|
+
const steps = yaml(page.match(/```yaml\n([\s\S]*?)\n```/)[1]);
|
|
45
|
+
assert.equal(steps.length, 1);
|
|
46
|
+
assert.deepEqual(Object.keys(steps[0].env).sort(), [
|
|
47
|
+
"CLOUDFLARE_ACCOUNT_ID",
|
|
48
|
+
"CLOUDFLARE_API_TOKEN",
|
|
49
|
+
"CLOUDFLARE_PAGES_PROJECT",
|
|
50
|
+
]);
|
|
51
|
+
assert.equal(steps[0].env.CLOUDFLARE_API_TOKEN, "${{ secrets.CLOUDFLARE_API_TOKEN }}");
|
|
52
|
+
assert.ok(existsSync(resolve(root, steps[0].run.slice("node ".length))));
|
|
53
|
+
process.stdout.write(
|
|
54
|
+
"Skill metadata, local resources, executable YAML mapping and all managed checksums verified.\n",
|
|
55
|
+
);
|
package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.mjs
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { pathToFileURL } from "node:url";
|
|
2
|
+
|
|
3
|
+
// GET-only user-token probe. No credential arguments, redirects or response dumps.
|
|
4
|
+
export async function verifyCloudflare(env = process.env, fetcher = globalThis.fetch) {
|
|
5
|
+
const token = env.CLOUDFLARE_API_TOKEN;
|
|
6
|
+
const account = env.CLOUDFLARE_ACCOUNT_ID;
|
|
7
|
+
const project = env.CLOUDFLARE_PAGES_PROJECT;
|
|
8
|
+
const result = {
|
|
9
|
+
credential: "unverified",
|
|
10
|
+
project_access: "unverified",
|
|
11
|
+
deployment: "unverified",
|
|
12
|
+
};
|
|
13
|
+
if (typeof token !== "string" || !token.trim() || /[\r\n]/.test(token)) {
|
|
14
|
+
return { ...result, error: "missing_or_invalid_CLOUDFLARE_API_TOKEN" };
|
|
15
|
+
}
|
|
16
|
+
if (!/^[a-fA-F0-9]{32}$/.test(account ?? "")) {
|
|
17
|
+
return { ...result, error: "invalid_CLOUDFLARE_ACCOUNT_ID" };
|
|
18
|
+
}
|
|
19
|
+
if (!/^[a-z0-9](?:[a-z0-9-]{0,56}[a-z0-9])?$/.test(project ?? "")) {
|
|
20
|
+
return { ...result, error: "invalid_CLOUDFLARE_PAGES_PROJECT" };
|
|
21
|
+
}
|
|
22
|
+
let stage = "credential";
|
|
23
|
+
async function get(path) {
|
|
24
|
+
const response = await fetcher("https://api.cloudflare.com/client/v4" + path, {
|
|
25
|
+
method: "GET",
|
|
26
|
+
headers: { Authorization: "Bearer " + token, Accept: "application/json" },
|
|
27
|
+
redirect: "error",
|
|
28
|
+
signal: AbortSignal.timeout(15000),
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
const status = Number.isInteger(response.status) ? response.status : "unknown";
|
|
32
|
+
return { error: stage + "_http_" + status };
|
|
33
|
+
}
|
|
34
|
+
const body = await response.json();
|
|
35
|
+
if (body?.success !== true || !body.result || typeof body.result !== "object") {
|
|
36
|
+
return { error: stage + "_invalid_response" };
|
|
37
|
+
}
|
|
38
|
+
return { value: body.result };
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const auth = await get("/user/tokens/verify");
|
|
42
|
+
if (auth.error) return { ...result, error: auth.error };
|
|
43
|
+
if (auth.value.status !== "active") return { ...result, error: "credential_not_active" };
|
|
44
|
+
result.credential = "verified";
|
|
45
|
+
stage = "project_access";
|
|
46
|
+
const access = await get("/accounts/" + account + "/pages/projects/" + project);
|
|
47
|
+
if (access.error) return { ...result, error: access.error };
|
|
48
|
+
if (access.value.name !== project) return { ...result, error: "project_identity_mismatch" };
|
|
49
|
+
result.project_access = "verified";
|
|
50
|
+
return result;
|
|
51
|
+
} catch {
|
|
52
|
+
// Fetch/parse exceptions can contain secrets or provider response text.
|
|
53
|
+
return { ...result, error: stage + "_transport_or_parse_error" };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
58
|
+
const result = await verifyCloudflare();
|
|
59
|
+
process.stdout.write(JSON.stringify(result) + "\n");
|
|
60
|
+
process.exitCode = result.error ? 1 : 0;
|
|
61
|
+
}
|
package/templates/.agents/skills/zaip-skill-github-actions-setup/scripts/verify-cloudflare.test.mjs
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { verifyCloudflare } from "./verify-cloudflare.mjs";
|
|
6
|
+
|
|
7
|
+
const secret = "synthetic-secret-do-not-log";
|
|
8
|
+
const env = {
|
|
9
|
+
CLOUDFLARE_API_TOKEN: secret,
|
|
10
|
+
CLOUDFLARE_ACCOUNT_ID: "a".repeat(32),
|
|
11
|
+
CLOUDFLARE_PAGES_PROJECT: "demo-preview",
|
|
12
|
+
};
|
|
13
|
+
const response = (result, status = 200, success = true) => ({
|
|
14
|
+
ok: status === 200,
|
|
15
|
+
status,
|
|
16
|
+
json: async () => ({ success, result }),
|
|
17
|
+
});
|
|
18
|
+
function queue(...responses) {
|
|
19
|
+
const calls = [];
|
|
20
|
+
const fetcher = async (url, options) => {
|
|
21
|
+
calls.push({ url, options });
|
|
22
|
+
const next = responses.shift();
|
|
23
|
+
if (next instanceof Error) throw next;
|
|
24
|
+
assert.ok(next, "unexpected request");
|
|
25
|
+
return next;
|
|
26
|
+
};
|
|
27
|
+
return { calls, fetcher };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
test("GET-only probe binds account/project, refuses redirects and does not claim deployment", async () => {
|
|
31
|
+
const q = queue(
|
|
32
|
+
response({ status: "active" }),
|
|
33
|
+
response({ name: env.CLOUDFLARE_PAGES_PROJECT, private_config: secret }),
|
|
34
|
+
);
|
|
35
|
+
assert.deepEqual(await verifyCloudflare(env, q.fetcher), {
|
|
36
|
+
credential: "verified",
|
|
37
|
+
project_access: "verified",
|
|
38
|
+
deployment: "unverified",
|
|
39
|
+
});
|
|
40
|
+
assert.equal(q.calls.length, 2);
|
|
41
|
+
assert.equal(
|
|
42
|
+
q.calls[1].url,
|
|
43
|
+
"https://api.cloudflare.com/client/v4/accounts/" +
|
|
44
|
+
"a".repeat(32) +
|
|
45
|
+
"/pages/projects/demo-preview",
|
|
46
|
+
);
|
|
47
|
+
for (const { options } of q.calls) {
|
|
48
|
+
assert.equal(options.method, "GET");
|
|
49
|
+
assert.equal(options.redirect, "error");
|
|
50
|
+
assert.equal(options.headers.Authorization, "Bearer " + secret);
|
|
51
|
+
assert.ok(options.signal instanceof AbortSignal);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
for (const [key, value] of [
|
|
56
|
+
["CLOUDFLARE_API_TOKEN", ""],
|
|
57
|
+
["CLOUDFLARE_API_TOKEN", "token\ninjection"],
|
|
58
|
+
["CLOUDFLARE_ACCOUNT_ID", "../other"],
|
|
59
|
+
["CLOUDFLARE_PAGES_PROJECT", "project?account=other"],
|
|
60
|
+
])
|
|
61
|
+
test("invalid input stops before network: " + key + "=" + JSON.stringify(value), async () => {
|
|
62
|
+
const q = queue();
|
|
63
|
+
const result = await verifyCloudflare({ ...env, [key]: value }, q.fetcher);
|
|
64
|
+
assert.ok(result.error);
|
|
65
|
+
assert.equal(q.calls.length, 0);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("expired token never probes project", async () => {
|
|
69
|
+
const q = queue(response({ status: "expired" }));
|
|
70
|
+
const result = await verifyCloudflare(env, q.fetcher);
|
|
71
|
+
assert.equal(result.error, "credential_not_active");
|
|
72
|
+
assert.equal(q.calls.length, 1);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
for (const status of [401, 403, 404])
|
|
76
|
+
test("project HTTP " + status + " stays unverified with no provider body", async () => {
|
|
77
|
+
const q = queue(response({ status: "active" }), response({ name: secret }, status));
|
|
78
|
+
const result = await verifyCloudflare(env, q.fetcher);
|
|
79
|
+
assert.equal(result.credential, "verified");
|
|
80
|
+
assert.equal(result.project_access, "unverified");
|
|
81
|
+
assert.equal(result.error, "project_access_http_" + status);
|
|
82
|
+
assert.ok(!JSON.stringify(result).includes(secret));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test("successful HTTP with API failure is not valid authentication", async () => {
|
|
86
|
+
const q = queue(response({ status: "active" }, 200, false));
|
|
87
|
+
assert.equal((await verifyCloudflare(env, q.fetcher)).credential, "unverified");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("wrong project identity is rejected", async () => {
|
|
91
|
+
const q = queue(response({ status: "active" }), response({ name: "another-project" }));
|
|
92
|
+
assert.equal((await verifyCloudflare(env, q.fetcher)).error, "project_identity_mismatch");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
for (const failure of [
|
|
96
|
+
new Error("network error " + secret),
|
|
97
|
+
{
|
|
98
|
+
ok: true,
|
|
99
|
+
status: 200,
|
|
100
|
+
json: async () => {
|
|
101
|
+
throw new Error(secret);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
])
|
|
105
|
+
test("transport/parse exceptions are sanitized", async () => {
|
|
106
|
+
const result = await verifyCloudflare(env, queue(failure).fetcher);
|
|
107
|
+
assert.equal(result.error, "credential_transport_or_parse_error");
|
|
108
|
+
assert.ok(!JSON.stringify(result).includes(secret));
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("CLI rejects missing configuration with nonzero exit and sanitized output", () => {
|
|
112
|
+
const child = spawnSync(
|
|
113
|
+
process.execPath,
|
|
114
|
+
[fileURLToPath(new URL("./verify-cloudflare.mjs", import.meta.url))],
|
|
115
|
+
{
|
|
116
|
+
encoding: "utf8",
|
|
117
|
+
env: {
|
|
118
|
+
...process.env,
|
|
119
|
+
CLOUDFLARE_API_TOKEN: "",
|
|
120
|
+
CLOUDFLARE_ACCOUNT_ID: env.CLOUDFLARE_ACCOUNT_ID,
|
|
121
|
+
CLOUDFLARE_PAGES_PROJECT: env.CLOUDFLARE_PAGES_PROJECT,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
assert.equal(child.status, 1, child.stderr);
|
|
126
|
+
assert.equal(JSON.parse(child.stdout).error, "missing_or_invalid_CLOUDFLARE_API_TOKEN");
|
|
127
|
+
assert.equal(child.stderr, "");
|
|
128
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
|
|
9
|
+
function findBash() {
|
|
10
|
+
if (process.platform !== "win32") return "bash";
|
|
11
|
+
const git = spawnSync("where.exe", ["git.exe"], { encoding: "utf8" });
|
|
12
|
+
const candidates = (git.stdout ?? "")
|
|
13
|
+
.trim()
|
|
14
|
+
.split(/\r?\n/)
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.flatMap((file) => [
|
|
17
|
+
resolve(dirname(file), "../bin/bash.exe"),
|
|
18
|
+
resolve(dirname(file), "../../bin/bash.exe"),
|
|
19
|
+
]);
|
|
20
|
+
const match = candidates.find(existsSync);
|
|
21
|
+
assert.ok(match, "Git for Windows with Bash must be available on PATH for this integration test");
|
|
22
|
+
return match;
|
|
23
|
+
}
|
|
24
|
+
const bash = findBash();
|
|
25
|
+
const guide = await readFile(new URL("../references/hostinger-vps.md", import.meta.url), "utf8");
|
|
26
|
+
const snippet = guide.match(/```bash\n([\s\S]*?)\n```/)[1];
|
|
27
|
+
const toPosix = (value) =>
|
|
28
|
+
process.platform === "win32"
|
|
29
|
+
? value.replaceAll("\\", "/").replace(/^([A-Za-z]):/, (_, drive) => "/" + drive.toLowerCase())
|
|
30
|
+
: value;
|
|
31
|
+
|
|
32
|
+
async function runProbe(overrides = {}) {
|
|
33
|
+
const dir = await mkdtemp(join(tmpdir(), "zaip-ssh-probe-"));
|
|
34
|
+
const stub = join(dir, "ssh");
|
|
35
|
+
// Execute the actual guide snippet, substituting only the external SSH process.
|
|
36
|
+
await writeFile(
|
|
37
|
+
stub,
|
|
38
|
+
'#!/usr/bin/env bash\nset -eu\nprintf "%s\\n" "$@" > "$PROBE_ARGS"\ntest -s "$4"\nprintf "%s" "$4" > "$PROBE_KEY_PATH"\nif env | grep -q "^VPS_SSH_PRIVATE_KEY="; then exit 99; fi\nexit "${PROBE_EXIT:-0}"\n',
|
|
39
|
+
);
|
|
40
|
+
await chmod(stub, 0o700);
|
|
41
|
+
const script = join(dir, "probe.sh");
|
|
42
|
+
await writeFile(script, 'export PATH="' + toPosix(dir) + ':$PATH"\n' + snippet);
|
|
43
|
+
const argsFile = join(dir, "args.txt");
|
|
44
|
+
const keyPathFile = join(dir, "key-path.txt");
|
|
45
|
+
const child = spawnSync(bash, [toPosix(script)], {
|
|
46
|
+
encoding: "utf8",
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
VPS_HOST: "example.invalid",
|
|
50
|
+
VPS_PORT: "2222",
|
|
51
|
+
VPS_USER: "deploy",
|
|
52
|
+
VPS_SSH_PRIVATE_KEY: "synthetic-multiline\nprivate-key",
|
|
53
|
+
VPS_KNOWN_HOSTS: "[example.invalid]:2222 ssh-ed25519 synthetic-public",
|
|
54
|
+
PROBE_ARGS: toPosix(argsFile),
|
|
55
|
+
PROBE_KEY_PATH: toPosix(keyPathFile),
|
|
56
|
+
...overrides,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
let args = null;
|
|
60
|
+
try {
|
|
61
|
+
args = await readFile(argsFile, "utf8");
|
|
62
|
+
} catch {}
|
|
63
|
+
let cleanupExit = null;
|
|
64
|
+
try {
|
|
65
|
+
const keyPath = await readFile(keyPathFile, "utf8");
|
|
66
|
+
cleanupExit = spawnSync(bash, [
|
|
67
|
+
"-c",
|
|
68
|
+
'test ! -e "$1" && test ! -d "$(dirname "$1")"',
|
|
69
|
+
"--",
|
|
70
|
+
keyPath,
|
|
71
|
+
]).status;
|
|
72
|
+
} catch {}
|
|
73
|
+
assert.equal(dirname(resolve(dir)), resolve(tmpdir()));
|
|
74
|
+
assert.ok(basename(dir).startsWith("zaip-ssh-probe-"));
|
|
75
|
+
await rm(dir, { recursive: true, force: true });
|
|
76
|
+
return { ...child, args, cleanupExit };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
test("guide SSH test uses verified host, fixed read-only command and cleans key", async () => {
|
|
80
|
+
const result = await runProbe();
|
|
81
|
+
assert.equal(result.status, 0, result.stderr);
|
|
82
|
+
assert.match(result.args, /StrictHostKeyChecking=yes/);
|
|
83
|
+
assert.match(result.args, /BatchMode=yes/);
|
|
84
|
+
assert.match(result.args, /deploy@example.invalid\ntrue\n$/);
|
|
85
|
+
assert.equal(result.cleanupExit, 0);
|
|
86
|
+
assert.ok(!result.stdout.includes("private-key"));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("SSH failure is propagated and private material removed", async () => {
|
|
90
|
+
const result = await runProbe({ PROBE_EXIT: "255" });
|
|
91
|
+
assert.equal(result.status, 255, result.stderr);
|
|
92
|
+
assert.equal(result.cleanupExit, 0);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
for (const fields of [
|
|
96
|
+
{ VPS_HOST: "-oProxyCommand=bad" },
|
|
97
|
+
{ VPS_USER: "deploy;bad" },
|
|
98
|
+
{ VPS_PORT: "0" },
|
|
99
|
+
{ VPS_PORT: "65536" },
|
|
100
|
+
{ VPS_PORT: "22;bad" },
|
|
101
|
+
])
|
|
102
|
+
test("invalid SSH destination never executes SSH: " + JSON.stringify(fields), async () => {
|
|
103
|
+
const result = await runProbe(fields);
|
|
104
|
+
assert.equal(result.status, 2, result.stderr);
|
|
105
|
+
assert.equal(result.args, null);
|
|
106
|
+
});
|