Skip to content

Comments

fix(infrastructure): prevent .esbuild directory cleanup during packaging#542

Merged
seanspeaks merged 35 commits intofeature/integration-router-v2-drop-modules-routerfrom
claude/analyze-branch-merge-60O1x
Feb 22, 2026
Merged

fix(infrastructure): prevent .esbuild directory cleanup during packaging#542
seanspeaks merged 35 commits intofeature/integration-router-v2-drop-modules-routerfrom
claude/analyze-branch-merge-60O1x

Conversation

@seanspeaks
Copy link
Contributor

Problem

Deployment fails with ENOENT error during serverless packaging:

Error: ENOENT: no such file or directory, lstat '.esbuild/.serverless'

Root Cause

serverless-esbuild config had keepOutputDirectory: false, which causes:

  1. Frigg plugin creates .esbuild/.serverless directory
  2. serverless-esbuild packages functions
  3. serverless-esbuild DELETES .esbuild directory (cleanup)
  4. Later packaging step tries to access .esbuild/.serverless → ENOENT

Solution

Set keepOutputDirectory: true in base-definition-factory.js:227

Why This Is Safe:

  • Directory is lightweight (~few KB of metadata)
  • Subsequent deployments overwrite it anyway
  • Prevents race condition between packaging steps
  • Matches standard serverless-esbuild best practices

Testing

Local development unaffected (directory already exists during dev)
CI/CD will no longer fail with ENOENT during packaging

Impact

  • Fixes second deployment blocker (after Prisma layer fix)
  • Enables successful end-to-end deployment
  • No performance impact (directory is tiny)
  • Improves deployment reliability

🤖 Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

claude and others added 30 commits February 10, 2026 23:22
Add comprehensive plan for Admin Script Runner service aligned with
next branch architecture (command pattern, repository factories,
Prisma schemas, multi-database support).

Includes initial package structure for @friggframework/admin-scripts.
- Add AdminScriptBase.Definition following IntegrationBase pattern
  (ref: packages/core/integrations/integration-base.js:57-69)
- Add appDefinition.adminScripts schema update
  (ref: packages/devtools/infrastructure/domains/shared/types/app-definition.js)
- Make integrationFactory OPTIONAL for scripts that only need DB access
- Add AdminFriggCommands with repository pattern matching existing commands
- Include exact file references throughout plan
- ADR-5: Execution modes - sync (optional) vs async (default)
- ADR-6: Hybrid scheduling (Definition defaults + DB/API overrides)
- ADR-7: DDD/hexagonal architecture layers documented
- ADR-8: SchedulerAdapter port with AWS/local implementations
- ADR-9: AdminScriptBuilder following infrastructure-composer pattern
- Add ScriptSchedule Prisma model for hybrid scheduling
- Document deployment flow and generated serverless resources
- Update package structure with adapters directory
- Update Files to Create/Modify section with all new files
- ADR-10: Dry run via repository wrapper + HTTP interceptor
  - Intercepts DB writes, logs operations, returns unchanged data
  - Intercepts external API calls via mock axios instance
  - Script code unchanged between normal and dry-run modes
- ADR-11: Self-queuing for long-running scripts
  - Scripts chunk work and re-queue via frigg.queueScript()
  - Tracks parentExecutionId for lineage
  - No Step Functions complexity
- Remove VM sandbox (not needed for trusted adopter scripts)
- Update package structure with dry-run files
- Replace raw SQS code with QueuerUtil.send() and batchSend()
- Reference: packages/core/queues/queuer-util.js
- Added queueScriptBatch() for bulk operations
Phase 1 implementation of Admin Script Runner service:

Repository Layer:
- AdminApiKey repositories (MongoDB, PostgreSQL, DocumentDB)
- ScriptExecution repositories (MongoDB, PostgreSQL, DocumentDB)
- Factory pattern for database-agnostic creation
- 70 unit tests passing

Application Layer:
- createAdminScriptCommands() factory with:
  - API key management (create, validate, list, deactivate)
  - Execution lifecycle (create, update, complete)
  - bcrypt hashing for key security
- Error mapping to HTTP status codes

Infrastructure Layer:
- AdminScriptBuilder wired into infrastructure-composer
- Generates SQS queue, Lambda functions, EventBridge scheduler
- 33 unit tests passing

Prisma Schema:
- AdminApiKey model with scopes and expiration
- ScriptExecution model with status, logs, metrics
Application Layer:
- AdminScriptBase: Base class for all admin scripts with Definition pattern
- ScriptFactory: Registry for script registration and instantiation
- AdminFriggCommands: Helper API for scripts (db access, queue, logging)
- ScriptRunner: Orchestrates script execution with error handling

Infrastructure Layer:
- admin-auth-middleware: Bearer token authentication for admin API keys
- admin-script-router: Express router with 5 endpoints for script management
- script-executor-handler: SQS worker Lambda for async execution

Features:
- Sync and async execution modes
- Self-queuing pattern via QueuerUtil for long-running scripts
- Audit trail (API key, IP address)
- Automatic log persistence to execution records

Test Coverage: 110 tests passing
…h check

Built-in Scripts:
- OAuthTokenRefreshScript: Refreshes OAuth tokens near expiry
  - Configurable expiry threshold (default 24h)
  - Dry-run mode for safe testing
  - Filters by integration IDs or all

- IntegrationHealthCheckScript: Checks integration health
  - Validates credential presence and expiry
  - Tests API connectivity
  - Optionally updates integration status
  - Schedule-ready (daily cron expression)

Both scripts:
- Extend AdminScriptBase with Definition pattern
- Use AdminFriggCommands for database/API access
- Include JSON Schema for input/output validation
- Comprehensive error handling and logging

Test Coverage: 41 tests passing for built-in scripts
Fixed a bug where the logs array from Prisma was being mutated
directly instead of creating a copy first. This caused test failures
when the original array reference was used for comparison.
Phase 2 - Hybrid Scheduling:
- ScriptSchedule Prisma model (MongoDB + PostgreSQL)
- ScriptSchedule repository implementations with factory
- SchedulerAdapter port interface (hexagonal pattern)
- AWSSchedulerAdapter for EventBridge Scheduler
- LocalSchedulerAdapter for dev/test
- Schedule management API endpoints:
  - GET /scripts/:name/schedule (DB override > Definition default)
  - PUT /scripts/:name/schedule (create/update override)
  - DELETE /scripts/:name/schedule (revert to default)
- Schedule commands in admin-script-commands.js

Phase 3 - Dry-Run Mode:
- DryRunRepositoryWrapper: Proxy-based write interception
- DryRunHttpInterceptor: Mock HTTP client with service detection
- Automatic sanitization of sensitive data in logs
- Returns preview with operation log and summary
- POST /execute { dryRun: true } support

Features:
- 20+ external service detection (HubSpot, Salesforce, Slack, etc.)
- Smart read vs write operation detection
- Timezone-aware scheduling
- AWS EventBridge rule tracking (ruleArn, ruleName)

Test Coverage: 424 tests passing (141 new tests added)
- Remove commented-out domain model placeholders (not needed with repository pattern)
- Remove commented-out factory function placeholder
- Clarify EventBridge Scheduler integration comments as optional enhancement
- Integrate createSchedulerAdapter into PUT /schedule endpoint
- Provision EventBridge rule when schedule is enabled with cron expression
- Delete EventBridge rule when schedule is disabled or deleted
- Store AWS rule ARN/name in database for tracking
- Handle scheduler errors gracefully (non-fatal, with warning in response)
- Add 6 new tests for scheduler integration
Align naming with AWS EventBridge Scheduler terminology:
- awsRuleArn → awsScheduleArn
- awsRuleName → awsScheduleName
- updateScheduleAwsRule → updateScheduleAwsInfo
- ruleArn → scheduleArn (adapter return values)
- ruleName → scheduleName (adapter return values)

This reflects that we use EventBridge Scheduler (the newer service),
not EventBridge Rules (the older approach).
Document the design decisions for the Admin Script Runner:
- Entry point via appDefinition.adminScripts
- Script base class pattern following IntegrationBase
- Infrastructure components (builder, repositories, handlers)
- Execution modes (sync/async)
- Hybrid scheduling with EventBridge Scheduler
- Dry-run mode for safe testing
- Security model with admin API keys

Also update README to include ADR-004 and ADR-005.
The admin-script-router requires express and serverless-http but they
were not declared in package.json, causing the release to fail.
The @unique constraint on keyHash already creates an index, so the
explicit @@index([keyHash]) was causing a "Index already exists" error.
Replace global parseInt/isNaN with Number.parseInt/Number.isNaN
to follow JavaScript best practices and pass SonarCloud analysis.
- Extract ScheduleManagementUseCase from admin-script-router
  - Encapsulates schedule business logic (get/upsert/delete)
  - Handles EventBridge sync with graceful error handling
  - 14 unit tests with full coverage

- Refactor oauth-token-refresh.js
  - Extract _checkRefreshPrerequisites() for token validation
  - Extract _performTokenRefresh() for actual refresh logic
  - Extract _createResult() helper for consistent response format

- Refactor integration-health-check.js
  - Extract _createCheckResult() for initial result structure
  - Extract _runChecks() to orchestrate all checks
  - Extract _addCheckResult() to track issues
  - Extract _determineOverallStatus() for status logic
  - Extract _handleCheckError() for error handling

All 297 tests passing.
- Add id-token: write permission for OIDC authentication
- Add contents: write permission for release commits
- Upgrade npm to latest for trusted publishing support (requires 11.5.1+)
- Remove NPM_TOKEN/NODE_AUTH_TOKEN (OIDC replaces token auth)

Requires configuring trusted publishers on npmjs.com for each package.
Keep both OIDC permissions and NPM_TOKEN for flexibility:
- Packages with trusted publisher configured → use OIDC
- New packages (e.g., admin-scripts) → fall back to token

This allows gradual migration to OIDC while supporting new package publishes.
Phase 1 of admin refactoring based on Daniel's PR review:

1. Auth simplification (ENV-based like db-migrate):
   - Add shared validateAdminApiKey middleware in core/handlers/middleware
   - Delete AdminApiKey model, repositories, and tests
   - Remove API key commands from admin-script-commands.js

2. Schema changes:
   - Replace AdminApiKey + ScriptExecution with AdminProcess model
   - AdminProcess mirrors Process but without user/integration FK
   - Supports hierarchy (parentProcessId, childProcesses)
   - Used for: admin scripts, db migrations, system tasks

3. Files deleted:
   - admin-api-key-repository-*.js (all variants)
   - admin-api-key tests

Next steps: Create AdminProcess repository, refactor routes to
/admin/scripts/:name convention, unify db-migrate under /admin.
…r /admin

Major refactoring based on PR feedback:

1. AdminProcess Repository (replaces ScriptExecution):
   - New: admin-process-repository-interface.js
   - New: admin-process-repository-mongo.js
   - New: admin-process-repository-postgres.js
   - New: admin-process-repository-documentdb.js
   - New: admin-process-repository-factory.js
   - Deleted: All script-execution-repository-* files

2. Updated admin-scripts package:
   - All files now use AdminProcess methods
   - Updated: admin-script-base.js, admin-frigg-commands.js, script-runner.js
   - Updated: admin-script-router.js, script-executor-handler.js
   - Fixed export: validateAdminApiKey (not adminAuthMiddleware)

3. Moved db-migrate under /admin path:
   - Routes: /admin/db-migrate/*
   - Uses shared validateAdminApiKey middleware
   - Updated use-cases and tests

4. Cleaned up obsolete code:
   - Removed AdminApiKey tests from admin-script-commands.test.js
   - Updated all tests for AdminProcess methods

All 295 tests passing.
Address PR feedback from Daniel:

1. Simplified dry-run implementation:
   - Deleted over-engineered dry-run-repository-wrapper.js (262 lines)
   - Deleted over-engineered dry-run-http-interceptor.js (297 lines)
   - New dry-run validates inputs and returns preview without executing
   - Added JSON schema validation for script parameters
   - Net reduction: ~990 lines removed

2. Cleaned up package.json:
   - Removed unused mongoose dependency
   - Removed unused chai devDependency
   - Kept supertest for Express route testing (different from nock)

3. Documented admin-script-commands architecture:
   - Explained why separate from integration-commands
   - integration-commands: user-context operations (requires integrationClass)
   - admin-script-commands: system operations (no user context)
   - Separation follows SRP and avoids coupling

Tests: 262 passing
…Runner

Changes:
- Rename requiresIntegrationFactory to requireIntegrationInstance (PR feedback)
- Add JSDoc documentation for executionId parameter
- Split schedule-management-use-case.js into 3 separate use cases following SRP:
  - GetEffectiveScheduleUseCase
  - UpsertScheduleUseCase
  - DeleteScheduleUseCase
- Abstract AWS-specific naming to generic external scheduler terminology:
  - awsScheduleArn → externalScheduleId
  - awsScheduleName → externalScheduleName
  - updateScheduleAwsInfo → updateScheduleExternalInfo
- Remove sinon dependency, use Jest mocks instead
- Update Prisma schemas for both MongoDB and PostgreSQL
- Update ADR documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ename context

- Rename AdminFriggCommands → AdminScriptContext (facade pattern)
- Refactor to constructor injection (context via constructor, not execute)
- Remove logging from AdminScriptBase (use context.log instead)
- Clean up display object - only UI-specific overrides
- Strip verbose JSDoc comments (keep code sparse)
- Update all tests for new API
- Add PR review tracker for remaining items

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…leanup

- Remove hardcoded defaults and env var auto-detection from scheduler
  adapters; require explicit config from appDefinition pattern
- Region inherits from AWS_REGION (Lambda runtime), not per-adapter config
- Make trigger required in ScriptRunner.execute()
- Fix status->state bug in script-executor-handler error path
- Remove PR_517_REVIEW_TRACKER.md from repo
- Regenerate package-lock.json (remove stale mongoose/chai/sinon)
- Remove detectSchedulerAdapterType and its export

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… handler

- Extract dry-run validation from ScriptRunner into standalone
  validateScriptInput() with dedicated POST /scripts/:name/validate route
- Simplify script-executor-handler to thin SQS adapter; runner handles
  all error recording and status updates
- Change async execution response status from PENDING to QUEUED
- Remove dryRun param from execute endpoint (separate concerns)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d SQS validation

- Remove 12 thin wrapper methods from AdminScriptContext; scripts now
  access repos directly via context.integrationRepository, etc.
- Remove DB log persistence from log(); in-memory only now
- Remove adminProcessRepository lazy getter (no longer needed)
- Add JSDoc documenting AdminScriptContext's unique value
- Remove 5 static helpers from AdminScriptBase (getName, getDefinition, etc.)
- Update builtin scripts to use repos directly
- Add scriptName/executionId validation in SQS handler
- Update all tests (-529/+149 lines)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
seanspeaks and others added 5 commits February 16, 2026 02:43
…, queue validation, unused deps

- Pass scheduler config from env vars to createSchedulerAdapter() instead of empty call
- Validate ADMIN_SCRIPT_QUEUE_URL before async execution, return 503 if not configured
- Remove unused bcryptjs, lodash, uuid dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…racking, adapter format

- AWS scheduler createSchedule now uses upsert pattern: tries CreateScheduleCommand
  first, falls back to UpdateScheduleCommand on ConflictException, preventing
  stale schedules when cron expressions are edited
- SQS handler catch block now calls completeAdminProcess with state: 'FAILED'
  when executionId is available, preventing orphaned execution records stuck
  in non-terminal state
- LocalSchedulerAdapter.listSchedules() now returns normalized format matching
  AWS adapter contract (Name, State, ScheduleExpression, ScheduleExpressionTimezone)

https://claude.ai/code/session_01BRAKMNfvY2Fpnwac7gbuq3
Resolves merge conflicts by taking the admin-script-runner branch's versions
for admin-scripts models (AdminProcess pattern), /admin/ route prefixes,
admin auth middleware, and vendor-agnostic scheduler naming.

https://claude.ai/code/session_01UTMSBwVwDXaGTmtnNJ8VX6
… exports

- Fix method name mismatch in admin-script-commands.js: commands now call
  repository interface methods (createProcess, findProcessById, etc.) instead
  of non-existent domain-specific names (createAdminProcess, etc.)
- Translate command params to repository format (scriptName→name, type→ADMIN_SCRIPT,
  context object for scriptVersion/trigger/mode/input/audit)
- Consolidate completeAdminProcess to use single updateProcessResults call
  instead of separate updateOutput/updateError/updateMetrics methods
- Export createAdminScriptCommands from application/index.js and core/index.js
- Standardize requireAdmin middleware to use x-frigg-admin-api-key header
  (consistent with validateAdminApiKey middleware)
- Add missing mock for script-schedule-repository-factory in tests
- Update all test assertions to match new repository interface contract

https://claude.ai/code/session_01UTMSBwVwDXaGTmtnNJ8VX6
@seanspeaks seanspeaks changed the base branch from main to feature/integration-router-v2-drop-modules-router February 22, 2026 02:14
@gitguardian
Copy link

gitguardian bot commented Feb 22, 2026

⚠️ GitGuardian has uncovered 2 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
22520632 Triggered Generic High Entropy Secret 29da1f3 packages/core/credential/repositories/tests/credential-repository-documentdb-encryption.test.js View secret
23374074 Triggered Generic Password 8c6a058 packages/devtools/frigg-cli/start-command/infrastructure/DatabaseAdapter.js View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@seanspeaks seanspeaks merged commit 0eec050 into feature/integration-router-v2-drop-modules-router Feb 22, 2026
9 of 24 checks passed
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
354 Security Hotspots
5.7% Duplication on New Code (required ≤ 3%)
D Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants