Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
fccfa60
Import prepared Dispatch Core source
dillonlille Sep 12, 2026
0fdb8de
Import prepared Dispatch DSP source
dillonlille Sep 12, 2026
4a2d208
Add guarded Core release publication and GitHub workflow (#1)
dillonlille Sep 12, 2026
0789d5c
Add independent DSP checks and guarded release workflow (#1)
dillonlille Sep 12, 2026
b817a87
Use Core 0.0.1 bundle and wait for rendered browser fixtures (#2)
dillonlille Sep 12, 2026
5562549
Enable independent Core and DSP owner updates (#2)
dillonlille Sep 12, 2026
fbf0843
Fix public Core health probes and missing backend rollback (#3)
dillonlille Sep 12, 2026
65e9549
Fix Paycom credential saves under DSP capacity contention (#4)
dillonlille Sep 13, 2026
d36c4f8
Install optional plugin code only into DSPs that use it (#5)
dillonlille Sep 13, 2026
7cd9fc4
Verify Paycom immediately after saving credentials (#6)
dillonlille Sep 13, 2026
cab7d9d
Open Paycom workspace once its connection is verified (#3)
dillonlille Sep 13, 2026
6779519
Recover verified SQLite sidecars during DSP backup erasure (#7)
dillonlille Sep 13, 2026
a0b69c3
Add centered DSP home development notice (#8)
dillonlille Sep 13, 2026
2923c41
Import Core source with its complete history
dillonlille Sep 13, 2026
e6959af
Import DSP source with its complete history
dillonlille Sep 13, 2026
4012a8f
Unify platform releases and isolate DSP dashboards and plugin catalogs
dillonlille Sep 13, 2026
385a341
Verify shared dashboard rollout and preserve existing update behavior
dillonlille Sep 13, 2026
7b3a97f
Test unified release metadata and freeze legacy dashboards for migration
dillonlille Sep 13, 2026
021853f
Keep plugin previews and portable dashboard build commands working
dillonlille Sep 13, 2026
42df594
Preserve historical release selection and verify owner DSP dashboard …
dillonlille Sep 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions .github/actions/prepare-test-host/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Prepare isolated DSP test tools
description: Satisfy the DSP's existing trusted-tool rules on a disposable hosted runner
runs:
using: composite
steps:
- name: Require an isolated GitHub-hosted runner
shell: bash
env:
RUNNER_KIND: ${{ runner.environment }}
run: test "$RUNNER_KIND" = github-hosted
- name: Prepare trusted Node and Chrome paths
shell: bash
run: |
# Hosted tool caches may have writable parents. Do not weaken runtime checks.
sudo install -d -o root -g root -m 755 /dispatch-ci /dispatch-ci/bin
sudo install -o root -g root -m 755 "$(command -v node)" /dispatch-ci/bin/node
echo /dispatch-ci/bin >> "$GITHUB_PATH"
test -x /opt/google/chrome/chrome
sudo chown root:root /opt /opt/google
sudo chown -R root:root /opt/google/chrome
sudo chmod go-w /opt /opt/google /opt/google/chrome
sudo chmod -R go-w /opt/google/chrome
sudo chmod 4755 /opt/google/chrome/chrome-sandbox
stat -Lc '%u %a %n' /opt /opt/google /opt/google/chrome /opt/google/chrome/chrome /dispatch-ci/bin/node
echo 'DISPATCH_CHROME_EXECUTABLE=/opt/google/chrome/chrome' >> "$GITHUB_ENV"
command -v Xvfb
command -v setpriv
/usr/bin/python3 -c "import ctypes; ctypes.CDLL('libX11.so.6'); ctypes.CDLL('libXtst.so.6')"
2 changes: 2 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Describe the resulting behavior and relevant verification. Identify Core, DSP and
plugin changes, compatibility requirements, and any migration steps.
44 changes: 44 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Platform checks
on:
pull_request:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: platform-checks-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
platform:
runs-on: ubuntu-24.04
timeout-minutes: 40
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: 22
cache: npm
cache-dependency-path: |
core/dashboard/package-lock.json
dsp/dashboard/package-lock.json
dsp/tooling/frontend/package-lock.json
- uses: ./.github/actions/prepare-test-host
- run: npm run bootstrap -- "$RUNNER_TEMP/platform"
- run: npm run check -- "$RUNNER_TEMP/platform"
- run: npm run build -- "$RUNNER_TEMP/platform"
- run: npm test -- "$RUNNER_TEMP/platform"
- run: npm run test:integration -- "$RUNNER_TEMP/platform"
- name: Verify updates in browser
run: |
cd "$RUNNER_TEMP/platform/core/dashboard"
npx playwright install --with-deps chromium
npx playwright test --config playwright.updates.config.cjs
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
if: always()
with:
name: verification
path: /tmp/dispatch-updates-browser
retention-days: 7
62 changes: 62 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Publish platform release
on:
workflow_dispatch:
inputs:
version:
description: Owner-selected X.Y.Z platform version
required: true
type: string
expected_main:
description: Tested main commit (40 characters)
required: true
type: string
changes:
description: Reviewed JSON changelog with core, dsp and plugins strings
required: true
type: string
concurrency:
group: platform-publication
cancel-in-progress: false
permissions:
contents: read
jobs:
publish:
if: github.ref == 'refs/heads/main' && inputs.expected_main == github.sha
runs-on: ubuntu-24.04
timeout-minutes: 30
permissions:
contents: write
actions: read
id-token: write
attestations: write
env:
RELEASE_VERSION: ${{ inputs.version }}
RELEASE_COMMIT: ${{ inputs.expected_main }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
ref: ${{ inputs.expected_main }}
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020
with:
node-version: 22
- name: Verify main and unused version
env:
GH_TOKEN: ${{ github.token }}
run: node tooling/release.cjs guard
- run: npm run bootstrap -- "$RUNNER_TEMP/platform"
- run: npm run check -- "$RUNNER_TEMP/platform"
- run: npm run build -- "$RUNNER_TEMP/platform"
- name: Package platform release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_CHANGES: ${{ inputs.changes }}
run: node tooling/release.cjs package "$RUNNER_TEMP/platform" "$RUNNER_TEMP/publication"
- uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8
with:
subject-path: ${{ runner.temp }}/publication/*
- name: Publish verified release
env:
GH_TOKEN: ${{ github.token }}
run: node tooling/release.cjs publish "$RUNNER_TEMP/publication"
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules/
__pycache__/
*.pyc
.env
.env.*
playwright-report/
test-results/
core/dashboard/public/assets/frontend.js
core/dashboard/public/assets/styles.css
dsp/dashboard/public/assets/frontend.js
dsp/dashboard/public/assets/styles.css
21 changes: 21 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Dispatch Platform

Public repository: dillonlille/dispatch-platform. Keep credentials, DSP data and
host configuration outside source. Develop in isolated feature branches; PRs may
be created and merged autonomously after review and passing checks.

- core/: Platform Owner dashboard, shared API/services, host isolation, updater
and SDK source. Existing internal service modules remain under core/core/.
- dsp/: DSP runtime and DSP-owned dashboard entry point/pages.
- plugins/: optional plugin source, including Paycom; released with DSP updates.
- shared/dashboard/: shared UI source compiled separately into each dashboard.
- tooling/: monorepo assembly, checks, publication and migration helpers.

Read DEVELOPMENT.md and RELEASES.md. Build/test in an external synthetic workspace.
SDK/support packages are real versioned copies. Dashboard assets are central per
release; each DSP selects its approved version and owns its installed plugins and
private state. Core builds must not contain DSP-owned dashboard pages.

One user-requested vX.Y.Z release contains Core/DSP packages and three changelog
sections. Ask for a version unless supplied. Publishing never installs. Update Core
and Update Dev → Rollout Update are independent owner-controlled installation paths.
35 changes: 35 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Development

Use Node 22/24, npm, Python 3 and Linux. Build in a new directory outside source:

```sh
npm run bootstrap -- /absolute/build/workspace
npm run check -- /absolute/build/workspace
npm run build -- /absolute/build/workspace
npm test -- /absolute/build/workspace
npm run test:integration -- /absolute/build/workspace
```

Bootstrap assembles portable Core and DSP source trees, copies top-level plugins
into the DSP build workspace, merges shared UI source with each product's owned
entry points, and installs locked compiler dependencies plus versioned SDK copies.
These assembled trees are disposable, not additional source repositories. After
editing source, bootstrap a fresh workspace before final verification.

DSP browser collector tests need trusted Chrome, Xvfb, setpriv and X11 libraries;
the hosted checks prepare these on an isolated runner. Tests use synthetic data.

Use feature branches and PRs. The owner authorizes autonomous PR creation and
merging after review and successful checks. Publication and installation remain
separate. See RELEASES.md. Never develop in live/ or installed DSP directories.

After building both dashboards, run plugin previews from the assembled Core tree:

```sh
/absolute/build/workspace/core/bin/dispatch create plugin sample-notes
/absolute/build/workspace/core/bin/dispatch plugin dev /absolute/plugin/source
```

The preview serves each synthetic DSP's DSP dashboard and uses independent test
accounts/state. An external DSP dashboard can be supplied through the explicit
DISPATCH_DSP_DASHBOARD development setting. Production always uses release receipts.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
# Dispatch Platform

Core services, DSP dashboard/runtime, and optional plugins in one repository.
Core installation and Dev-first DSP rollout remain independent.
One repository and one platform release, with independent Core installation and
Dev-first DSP rollout.

- [core/](core/): Platform Owner dashboard, API, SDK and shared services.
- [dsp/](dsp/): DSP dashboard and runtime.
- [plugins/](plugins/): Paycom and future optional plugins, released with DSP updates.
- [shared/](shared/): reusable dashboard source compiled separately per product.
- [tooling/](tooling/): development, verification, publication and migration.

The Updates page groups Core, DSP and Plugins changes. **Update Core** installs
Core. **Update Dev → Rollout Update** installs the complete DSP experience,
including installed plugins and the approved catalog. Dashboard assets are stored
centrally per release; DSP credentials, settings and databases remain independent.

See [DEVELOPMENT.md](DEVELOPMENT.md), [RELEASES.md](RELEASES.md) and [AGENTS.md](AGENTS.md).
No deployment credentials or DSP private data belong in this public repository.
35 changes: 35 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Platform releases

One public repository and one platform version: vX.Y.Z. Prepare only on request.
Report the last published release, installed versions and changes under Core,
DSP and Plugins, then ask for a clickable patch/minor/major version unless supplied.

The manual release.yml workflow accepts version, expected_main and changes (a JSON
object with core/dsp/plugins strings). It requires successful main checks, builds
immutable artifacts, verifies provenance and uploaded bytes, and publishes one
release. No deployment credentials are used by GitHub. Existing tags are immutable.

platform-release.json binds the Core and DSP component digests. Unchanged components
reference the last release containing those exact packages, so plugin-only changes
never create a Core update. Shared source changes rebuild affected products. Core
and DSP manifests/archives have distinct asset names. SDK and plugin package
versions must change when their installed bytes change.

The single owner Updates page has Core, DSP and Plugins sections. Update Core
installs only the selected release's Core package. Update Dev installs the DSP
package only on permanent Dev: dashboard, runtime, installed plugins and catalog.
Plugin-only changes are DSP updates. Other DSPs keep their current dashboard and
catalog. The owner tests Dev and clicks Rollout Update for sequential activation.
New candidates require another Dev test; active rollouts keep their pinned digest.
Failures pause rollout. Credentials/settings/databases remain independent.

Core APIs must support installed DSP protocol versions; incompatible activation
is rejected. A Core update never rewrites DSP dependency copies. DSP dashboards
are cached centrally once per release and selected through authenticated sessions.
New DSPs use the completed production rollout and only builtin Cortex by default.

Migration retains legacy manifests and freezes the currently deployed dashboard
for DSP releases that predate dashboard packaging. Do not remove old repositories
or release assets while installed/rollback references still use them. The initial
bootstrap requires verified release assets, an idle updater, dashboard snapshots,
and a reversible Core activation. Publishing alone does not perform this cutover.
22 changes: 22 additions & 0 deletions core/.containerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
**
!.containerignore
!runtime/
!runtime/**
!shared/
!shared/**
**/tests
**/test
**/examples
**/integration
**/scripts
**/*.md
**/node_modules
**/state
**/data
**/secrets
**/references
**/Containerfile
# Provider health commands are runtime entrypoints; other scripts are development tools.
!compatibility/providers/*/scripts
compatibility/providers/*/scripts/*
!compatibility/providers/*/scripts/health
17 changes: 17 additions & 0 deletions core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
node_modules/
__pycache__/
*.pyc
.env
.env.*
!.env.example
*.sqlite
*.sqlite3
*.sqlite3-*
*.db
*.db-*
*.log
*.har
playwright-report/
test-results/
coverage/
.DS_Store
4 changes: 4 additions & 0 deletions core/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Core component

Read ../AGENTS.md, ../DEVELOPMENT.md and ../RELEASES.md. This directory is part
of the dispatch-platform monorepo. Root tooling assembles portable product builds.
3 changes: 3 additions & 0 deletions core/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Development

Use the monorepo commands in [../DEVELOPMENT.md](../DEVELOPMENT.md).
20 changes: 20 additions & 0 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dispatch Core

Shared services and dashboard for Dispatch. This project owns the complete web
application, platform-owner features, API, SDK source, authentication/browser
coordination, host management and update coordination.

DSP runtime and plugin source belong to the separate `dispatch-dsp` project.
Each product builds independently, with explicit versioned dependency packages.
Every DSP retains its own installed code and private state.

- [Directory map](AGENTS.md)
- [Local development](DEVELOPMENT.md)
- [PR and release workflow](RELEASES.md)
- [Independent update operations](core/updates/README.md)
- [Architecture and storage](docs/architecture.md)
- [Security policy](SECURITY.md)

Core and DSP use separate public repositories and release versions. Publishing a
GitHub release makes it available; installing it is a separate owner action. See
the update operations guide for initial deployment and recovery prerequisites.
3 changes: 3 additions & 0 deletions core/RELEASES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Releases

Use the platform workflow in [../RELEASES.md](../RELEASES.md).
40 changes: 40 additions & 0 deletions core/SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: Repository security policy
status: current
last_verified: 2026-09-02
---

# Security policy

## Sensitive data boundary

This repository must never contain:

- passwords, PINs, recovery answers, API tokens, cookies, or authorization headers;
- Auth Broker master keys or credential databases;
- browser profiles, login databases, session storage, or authenticated caches;
- Paycom, CDF, Collection Manager, Access Control, Provisioner, or other operational databases and backups;
- employee, customer, provider, or account data copied from a live system;
- sockets, service records, logs, staging candidates, or runtime state.

Use synthetic fixtures for tests and documentation. Local operational state belongs in an external owner-private directory configured through `DISPATCH_LOCAL_ROOT` or explicit absolute runtime roots.

Managed installation tests must use temporary synthetic organization/runtime identities and credential-free provider/publication evidence. Do not copy a live installation manifest, outbox/job record, Auth Broker profile, collection batch, publication target, or readiness snapshot into Git. Installation lifecycle repair uses the durable reconciler or closed activation retry—never direct SQL or filesystem edits.

## Reporting a vulnerability

Do not include secret values, personal data, browser artifacts, or live provider responses in a public issue. Contact the repository owner privately or use GitHub private vulnerability reporting when it is enabled.

Include only the minimum sanitized reproduction details needed to understand the problem.

## Accidental exposure

If a credential, key, cookie, browser profile, or private database is pushed, treat it as compromised even if the commit is later deleted:

1. Revoke or rotate the affected credential or key.
2. Invalidate related browser sessions.
3. Preserve a private incident record without copying secret values into Git.
4. Remove the data from Git history and verify the rewritten remote.
5. Review forks, clones, pull-request diffs, workflow artifacts, and caches for continued exposure.

See [runtime/auth-broker/SECURITY.md](runtime/auth-broker/SECURITY.md) for the component trust model and storage requirements.
12 changes: 12 additions & 0 deletions core/bin/dispatch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env -S node --no-warnings
'use strict';
process.umask(0o077);
const controller = new AbortController();
process.once('SIGINT', () => controller.abort());
if (['create', 'plugin'].includes(process.argv[2])) {
require('../tooling/plugin-cli').main(process.argv.slice(2)).then(result => console.log(JSON.stringify(result))).catch(error => {
console.error(error.message); process.exitCode = 1;
});
} else {
process.stdout.write('Dispatch Core developer tools: create plugin ID | plugin generate/check/dev PATH\nDSP runtime commands belong to dispatch-dsp/bin/dispatch.\n');
}
Loading