- add output column to ScenarioRunStepEntity; exec step return value is JSON-serialised and stored
- expose helpers.getStepOutput(order) in exec code; negative order is relative to current step
- add get_scenario_run, wait_for_scenario_run, export_scenario, import_scenario MCP tools
- move Architecture, Key descriptors, MCP tools, Scenario, Development docs to docs/
- delete CONTRIBUTING.md (replaced by docs/development.md)
- add ScenarioRunLogEntity to persist step script output to DB
- stepLogger dual-writes to NestJS logger and DB (fire-and-forget)
- add GET /scenarios/:id/run/:runId returning run, stepRuns and logs
- add POST /scenarios/:id/run/:runId/wait (polls until terminal state)
- 9 new integration tests for the two endpoints (136 total)
- add eslint with typescript-eslint and eslint-config-prettier
- add npm scripts: format, lint, lint:fix
- resolve all lint errors across src and test (no any types)
- add CONTRIBUTING.md covering dev workflow
- replace two @Interval jobs (activate + process-one-step) with one job
that spawns an async loop per run, eliminating 1-second gaps between steps
- track active runs via Set to prevent duplicate processing
- wrap each run loop in traceStorage.run() with a fresh UUID so all log
lines for a run share a trace ID without an HTTP request context
- avoids mutating the global console object entirely
- passes fakeConsole as a named parameter so the script's lexical console
is the intercepted version without any save/restore dance
- eliminates concurrency hazard when multiple scripts run concurrently
- suppress raw stdout from exec/validate code by overriding console
- route console.log/warn/error/info through ScriptLogger callback
- expose helpers.log/warn/error for scripts to use explicitly
- scheduler passes step-run-prefixed logger to all execute() calls
- log response body length instead of full body in LoggingInterceptor
- all steps in a run share one browser/page instance so wizard state persists
- add 'sign' step type: execCode is {keyId} and signs via EDS widget on current page
- extract AuthService.loadKeyDescriptor() to deduplicate key file parsing
- extend StepType, DTOs, and MCP enums to include 'sign'
- override getTimestamp() to emit ISO 8601 instead of locale string
- override formatMessage() to drop PID prefix and level padding
- enable timestamp: true so timestampDiff (+Nms) appears on each line
- pass TraceLogger instance to NestFactory so framework logs use same format
- add TraceInterceptor that reads x-trace-id header or generates a UUID
- add AsyncLocalStorage store in common/trace-context for request-scoped trace ID
- replace NestJS Logger with TraceLogger (extends ConsoleLogger) that injects trace ID into log context
- register TraceInterceptor globally before LoggingInterceptor
- move HealthController into HealthModule so global interceptors apply to /healthz
- omit body/response from log lines when empty or null
- server instantiated once in constructor, tools registered once
- per-request transport created fresh and closed in finally to reset server state
- name and version sourced from package.json instead of hard-coded strings
- sessionName is now optional in open/exec; skips session restore when omitted
- add selector param to open: returns outerHTML or textContent of matched element
- extract session restore logic into private setupSession() to remove duplication
- replace per-exception instanceof checks with single HttpException base class check
- embed label into InternalServerErrorException message instead of logging separately
- update MCP tool schemas and HTTP DTOs to reflect optional sessionName and new selector
- add integration tests: sessionless open/exec, selector, selector+readerMode
- new dom-helpers.ts exports dumpDom(page, selector?) that evaluates a
browser-side tree walker returning a lean DomNode structure
- filters ignored tags (svg, script, path, etc.) and hidden elements
- captures role, data-testid, data-qa, data-action, data-element-id,
id, type, name, href (relativized), checked, disabled, and text
- prunes single-child non-significant divs; discards empty non-sig nodes
- code-executor wraps dumpDom in a pageHelpers object passed as helpers
param so user scripts can call helpers.dumpDom() or helpers.dumpDom('main')
- 29 unit tests covering all behaviours via fake DOM builder
- KeyDescriptor now accepts optional login field alongside keyFile
- when login is present, clicks login/password auth method, fills email+password fields, and submits
- file-key flow unchanged; validation ensures exactly one strategy is present
- system Chromium path from PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH was not forwarded
to the launch options, causing 'executable doesn't exist' errors in Docker
- add PaginationQueryDto<TOrderBy> generic with orderBy and orderDir fields
- add SessionOrderBy, EnvironmentOrderBy, ScenarioOrderBy type aliases
- update session, environment, scenario services and controllers to use typed pagination
- update MCP list_sessions, list_environments, list_scenarios tools to expose orderBy/orderDir
- update tests for all list endpoints to cover page, limit, ordering, and invalid param rejection
- add jest, ts-jest, supertest, and related dev dependencies
- add test scripts (test, test:debug, test:watch) to package.json
- add jest.config.js with ts-jest transform and module name mappers
- add controller specs for auth, browser, environment, mcp, scenario, session
- add mocks for jsdom, playwright, and readability
- add test/tsconfig.json and exclude test dir from main tsconfig
- install @nestjs/schedule and register ScheduleModule in AppModule
- add ScenarioSchedulerService with two 1s interval jobs:
- activatePendingRuns: flips pending runs to in_progress
- processPendingStepRuns: executes next pending step run (login or exec),
runs optional validateCode, advances or fails the run accordingly
- on step pass: next waiting step becomes pending; last step pass flips run to pass
- on step fail: remaining steps set to cancelled, run flipped to fail
- add cancelled to RunStepStatus union
- add GET /scenarios/:id/runs with pagination and optional ?status= filter
- add ScenarioRunEntity (pending|in_progress|pass|fail) and ScenarioRunStepEntity (waiting|pending|in_progress|pass|fail)
- add POST /scenarios/:id/run — creates run with first step pending, rest waiting
- add order field to ScenarioStepEntity and ScenarioRunStepEntity for deterministic sequential execution
- findOne and createRun now sort steps/stepRuns by order ASC
- add ScenarioEntity and ScenarioStepEntity with cascade delete
- step fields: type (login|exec), sessionName (required), execCode, validateCode
- login steps create a named session; exec steps consume it by sessionName
- full CRUD controller under /scenarios and /scenarios/:id/steps
- paginated GET /scenarios with page/limit query params returning { data, total, page, limit }
- register ScenarioModule and entities in AppModule
- add HttpExceptionFilter logging BadRequestException at warn and InternalServerErrorException at error with cause chain
- add LoggingInterceptor logging request/response pairs at debug level with method, path, body, status, and duration
- extract CodeExecutorService into standalone CodeExecutorModule imported by BrowserModule and McpModule
- thread { cause: err } into all catch blocks across auth, browser, and code-executor services
- accepts sessionName, optional url, and arbitrary JS code string
- restores cookies and localStorage from session before execution
- exposes page and context to user code as async function arguments
- session not found now returns 404 instead of 400
- restores cookies and localStorage from DB before page navigation
- readerMode flag extracts plain text via @mozilla/readability (Firefox reader engine)
- add localStorage default '{}' on session entity for clean schema migrations
- automates file-key login on the ID portal using Playwright/Chromium
- captures token, cookies, and localStorage after successful redirect
- stores session data in SQLite via TypeORM (better-sqlite3)
- sessions are keyed by sessionName (auto-generated UUID if not provided)
- login URL, cabinet redirect URL, keys dir, and DB path are all configurable via env