Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
7fba4cd
feat(e2e): add Playwright end-to-end testing setup with PostgreSQL an…
Andre-Diamond Jun 1, 2026
a9c7bea
chore: update package manager to npm@11.14.1
Andre-Diamond Jun 2, 2026
461c005
feat: enhance wallet fixture and transaction handling
Andre-Diamond Jun 5, 2026
fbae808
Merge remote-tracking branch 'origin/preprod' into feature/add-playwr…
Andre-Diamond Jun 11, 2026
b30863f
chore: update Docker configurations and wallet handling
Andre-Diamond Jun 11, 2026
fffa210
Refactor code structure for improved readability and maintainability …
Andre-Diamond Jun 12, 2026
451ced9
feat: implement email notification system for wallet signatures
Andre-Diamond Jun 17, 2026
415c5f7
feat: add notification link base URL configuration for email notifica…
Andre-Diamond Jun 17, 2026
0c96618
feat: enhance wallet notification settings and email verification pro…
Andre-Diamond Jun 18, 2026
862bd1b
Merge remote-tracking branch 'origin/preprod' into feature/add-playwr…
Andre-Diamond Jun 22, 2026
922b904
Merge remote-tracking branch 'origin/preprod' into feature/email-noti…
Andre-Diamond Jun 22, 2026
4a53b3d
feat: add npm version installation step in CI workflows and Dockerfile
Andre-Diamond Jun 22, 2026
dd00755
feat: increase timeout for integration and unit tests, add Prisma cli…
Andre-Diamond Jun 22, 2026
194fbbc
Merge pull request #322 from MeshJS/feature/email-notification-center
Andre-Diamond Jun 22, 2026
55f668a
Merge remote-tracking branch 'origin/preprod' into feature/add-playwr…
Andre-Diamond Jun 22, 2026
3b746f0
chore: update dependencies and improve CI scripts
Andre-Diamond Jun 25, 2026
5426557
feat: enhance Playwright tests with improved authentication handling …
Andre-Diamond Jun 25, 2026
df910ff
feat: add concurrency configuration to Playwright workflows for mutua…
Andre-Diamond Jun 25, 2026
1461085
feat: enhance error handling for provider responses and add tests for…
Andre-Diamond Jun 25, 2026
ecc5b5b
feat: improve error handling in runScenarios and add tests for critic…
Andre-Diamond Jun 25, 2026
cceb650
feat: refactor Blockfrost API integration and enhance error handling …
Andre-Diamond Jun 25, 2026
6386e67
Merge pull request #323 from MeshJS/feature/add-playwright-tests
Andre-Diamond Jun 25, 2026
b2eda17
feat: implement email notification enhancements with signature contex…
Andre-Diamond Jun 26, 2026
057613b
fix(auth): create User after authorization so login isn't stuck on "A…
QSchlegel Jun 26, 2026
396232b
Merge pull request #324 from MeshJS/claude/clever-dijkstra-320ba9
QSchlegel Jun 26, 2026
e733f0f
Refactor governance proposal metadata handling
Andre-Diamond Jun 26, 2026
fd66765
Merge remote-tracking branch 'origin/preprod' into feature/email-noti…
Andre-Diamond Jun 29, 2026
b1923b7
Merge pull request #326 from MeshJS/feature/email-notification-center
Andre-Diamond Jun 29, 2026
d7b64d4
feat(landing,blog): add AI-agent section and SEO blog
QSchlegel Jun 29, 2026
f42bacb
Merge pull request #328 from MeshJS/claude/ai-agent-landing-seo-blog
QSchlegel Jun 29, 2026
f72dc6c
feat(ci): update Docker images and enhance proxy proposal caching mec…
Andre-Diamond Jul 1, 2026
14963c7
feat: add support for parallel branches in proxy full lifecycle scena…
Andre-Diamond Jul 1, 2026
3926f28
Add end-to-end tests for transaction validation, notification setting…
Andre-Diamond Jul 6, 2026
17e1efc
fix(db): enable RLS + deny-all PostgREST policies on tables added sin…
QSchlegel Jul 6, 2026
6bbb43f
fix(repo): remove stray .claude/worktrees gitlink and ignore worktree…
QSchlegel Jul 6, 2026
dcfc4ab
docs(roadmap): July status snapshot — Mesh 2.0 cutover blocked upstre…
QSchlegel Jul 6, 2026
1e5dae8
Merge pull request #332 from MeshJS/fix/enable-rls-followup-tables
QSchlegel Jul 6, 2026
89383da
Merge pull request #333 from MeshJS/fix/remove-stray-worktree-gitlink
QSchlegel Jul 6, 2026
e5bf1fe
Merge pull request #334 from MeshJS/docs/roadmap-m3-snapshot
QSchlegel Jul 6, 2026
d9e08ec
feat: add additional secrets for Playwright browser tests
Andre-Diamond Jul 6, 2026
2854a83
fix: update signing flow to handle rate-limit responses correctly
Andre-Diamond Jul 6, 2026
fc5c43a
fix: change retryStatuses type to readonly array for better immutability
Andre-Diamond Jul 6, 2026
32470a2
fix: improve wallet navigation flow in createWalletThroughUi function
Andre-Diamond Jul 6, 2026
5d27396
Merge pull request #335 from MeshJS/feature/add-playwright-tests
Andre-Diamond Jul 6, 2026
1329c64
refactor: remove redundant waitForLoadState calls and improve retry l…
Andre-Diamond Jul 13, 2026
44c1219
Merge pull request #336 from MeshJS/feature/add-playwright-tests
Andre-Diamond Jul 13, 2026
ec42d80
feat(governance): DRep vote history explorer with rationales + CSV ex…
QSchlegel Jul 20, 2026
10cfc26
fix(governance): public DRep explorer no longer requires a connected …
QSchlegel Jul 20, 2026
970d081
feat: add discover tab for CIP-0146 wallet import flow
Andre-Diamond Jul 20, 2026
4729dd3
Merge pull request #337 from MeshJS/claude/public-governance-network-…
QSchlegel Jul 20, 2026
57d80da
fix(governance): make the public DRep explorer readable in light mode
QSchlegel Jul 20, 2026
97cda40
fix(ux): keep the large UTXOS onboarding CTA out of page headers
QSchlegel Jul 20, 2026
a552628
Merge remote-tracking branch 'origin/preprod' into claude/drep-vote-h…
QSchlegel Jul 20, 2026
2188eaa
feat(governance): vote history + CSV export on the wallet governance …
QSchlegel Jul 20, 2026
53690a9
Merge pull request #338 from MeshJS/claude/drep-vote-history-csv-f7c058
QSchlegel Jul 20, 2026
9dfe91c
Merge pull request #339 from MeshJS/claude/drep-explorer-readability
QSchlegel Jul 20, 2026
ef872e9
feat: enhance wallet import flow with stake and dRep key recovery
Andre-Diamond Jul 21, 2026
cb6920d
feat: implement base address recovery for co-signers and update addre…
Andre-Diamond Jul 21, 2026
f157981
feat(bots): new bots register without an address by default
QSchlegel Jul 21, 2026
f75b921
feat: add advanced signer address adjustment option in import flow
Andre-Diamond Jul 21, 2026
03bf426
feat: increase timeout for Playwright expectations to handle cold app…
Andre-Diamond Jul 21, 2026
4ea437f
Merge pull request #340 from MeshJS/feature/reg-and-discover-wallet
Andre-Diamond Jul 21, 2026
0c812f3
feat(bots): API hardening from the drep-collective bot stress test
QSchlegel Jul 21, 2026
1fe5833
Merge pull request #341 from MeshJS/claude/bot-register-optional-address
QSchlegel Jul 21, 2026
e62ce0e
fix(bots): observer access is enough to draft ballots
QSchlegel Jul 21, 2026
491e762
Merge pull request #342 from MeshJS/claude/ballot-write-observer
QSchlegel Jul 21, 2026
5be3f14
feat(bots): ballot lifecycle, proposalId validation, and consistency …
QSchlegel Jul 21, 2026
9a51f27
Merge pull request #343 from MeshJS/claude/bot-backlog-round-2
QSchlegel Jul 21, 2026
ece0aeb
fix(ui): show bot wallet grants at a glance in the Bot accounts card
QSchlegel Jul 21, 2026
2340f34
Merge pull request #344 from MeshJS/claude/bot-ui-grants
QSchlegel Jul 21, 2026
f096a8c
feat(ui): bot accounts card on the wallets dashboard
QSchlegel Jul 21, 2026
46cae95
Merge pull request #345 from MeshJS/claude/home-bot-card
QSchlegel Jul 21, 2026
6687bb4
feat(seo): make the site + bot API legible to AI agents and crawlers
QSchlegel Jul 22, 2026
02e1785
feat(seo): list /llms.txt in the sitemap
QSchlegel Jul 22, 2026
0a395ba
Merge pull request #346 from MeshJS/claude/ai-crawler-bot-api-access
QSchlegel Jul 22, 2026
a49e59f
docs(roadmap): delivered-to-date section + Aug–Oct replan
QSchlegel Jul 26, 2026
3bea9dc
feat(roadmap): public /roadmap page with a workstream timeline
QSchlegel Jul 27, 2026
8ea199d
fix(roadmap): stop timeline bars painting over the frozen column
QSchlegel Jul 27, 2026
319f0e0
feat(roadmap): feature vault + interactive knowledge graph
QSchlegel Jul 27, 2026
80c9335
Merge pull request #347 from MeshJS/claude/roadmap-aug-oct-refresh
QSchlegel Jul 27, 2026
a336539
Merge pull request #350 from MeshJS/claude/roadmap-page
QSchlegel Jul 27, 2026
049b88d
fix(roadmap): render the feature graph per request, not at build time
QSchlegel Jul 27, 2026
629a652
Merge pull request #351 from MeshJS/claude/fix-graph-prerender
QSchlegel Jul 27, 2026
4df929a
fix(build): drop the !vault/** glob that broke the Railpack build
QSchlegel Jul 27, 2026
3e7f9a8
Merge pull request #352 from MeshJS/claude/fix-dockerignore-vault
QSchlegel Jul 27, 2026
f0d4e3e
feat(token-flow): implement token flow visualization for on-chain and…
Andre-Diamond Jul 27, 2026
4fdfd75
fix(roadmap): update CI improvements and email notification service s…
Andre-Diamond Jul 27, 2026
2394488
Merge remote-tracking branch 'origin/preprod' into feat/sign-off-tx-v…
Andre-Diamond Jul 27, 2026
9a3d73a
feat(token-flow): implement explorer-style visualization with address…
Andre-Diamond Jul 27, 2026
14c66fc
feat(notifications): enhance signature recipient handling and add tes…
Andre-Diamond Jul 29, 2026
1fca415
feat(token-flow): enhance UTxO handling with per-input edges and bloc…
Andre-Diamond Jul 30, 2026
4047a57
feat: implement transaction inspector and builder palette
Andre-Diamond Jul 30, 2026
ed5019a
feat: add token flow timeline visualization for wallet transactions
Andre-Diamond Jul 30, 2026
ba03912
feat(touched-tracking): implement touched state for output fields and…
Andre-Diamond Jul 31, 2026
4b2f46f
Add comprehensive tests for token flow utilities and notification router
Andre-Diamond Jul 31, 2026
791a46f
feat: update documentation for Playwright E2E tests and CI variables
Andre-Diamond Jul 31, 2026
5dfc204
feat: add notification outbox drain workflow for scheduled processing
Andre-Diamond Jul 31, 2026
3e4b349
Merge pull request #353 from MeshJS/feat/sign-off-tx-visualization
Andre-Diamond Jul 31, 2026
984aa46
fix: update roadmap months to reflect accurate timelines
Andre-Diamond Aug 3, 2026
32bbb7f
fix: swap Document Sign-Off and Transaction Visualization MVP tasks i…
Andre-Diamond Aug 12, 2026
d4d9fca
feat: enhance transaction editing and loading functionality
Andre-Diamond Aug 12, 2026
57c7721
feat: enhance token flow handling for pending transactions with chang…
Andre-Diamond Aug 12, 2026
129c702
feat(governance): add support for draft votes and rationale editing
Andre-Diamond Aug 12, 2026
a7d28cf
test: stop marking real modules as virtual in jest.mock
QSchlegel Aug 12, 2026
32217dc
feat(mcp): stateless Model Context Protocol endpoint
QSchlegel Aug 12, 2026
3f49455
feat(api): accept human JWTs on two bot-only v1 endpoints
QSchlegel Aug 12, 2026
9967f97
feat(oauth): OAuth 2.1 authorization server for the MCP endpoint
QSchlegel Aug 12, 2026
1c77473
docs: document the MCP endpoint and its OAuth server
QSchlegel Aug 12, 2026
b156c1a
Merge pull request #357 from MeshJS/claude/stateless-mcp-multisig-be984c
QSchlegel Aug 12, 2026
c852f52
feat: add stake editing to tx builder
Andre-Diamond Aug 12, 2026
324af4c
feat: add stake editing to tx builder
Andre-Diamond Aug 12, 2026
726f48b
feat(mcp): show and revoke MCP connections in the profile
QSchlegel Aug 12, 2026
dee15bf
Merge pull request #358 from MeshJS/claude/mcp-connections-ui
QSchlegel Aug 12, 2026
59b30c1
feat: add staking and voting functionality to transaction builder
Andre-Diamond Aug 12, 2026
9b74cd4
feat(mcp): governance tools, and a vendor-neutral setup guide
QSchlegel Aug 12, 2026
2630583
feat(mcp): governance tools, and a vendor-neutral setup guide
QSchlegel Aug 12, 2026
cf1e9f8
Merge pull request #361 from MeshJS/claude/mcp-connections-ui
QSchlegel Aug 12, 2026
6bba825
feat: enhance token flow visualization and styling across components
Andre-Diamond Aug 13, 2026
e75511f
Merge pull request #360 from MeshJS/claude/mcp-governance-tools
QSchlegel Aug 13, 2026
df99960
feat(homepage): add a "Connect via MCP" button to the hero CTA row
QSchlegel Aug 12, 2026
ca002a4
Merge pull request #359 from MeshJS/claude/hero-mcp-button
QSchlegel Aug 13, 2026
09a042a
feat(mcp): publish ballot rationales to IPFS, and close the open pin …
QSchlegel Aug 13, 2026
b18d2a3
Merge pull request #362 from MeshJS/claude/mcp-ipfs-rationale
QSchlegel Aug 13, 2026
07ad67b
feat(mcp): permissions management, per-wallet activity, and a publish…
QSchlegel Aug 13, 2026
31374d5
Merge pull request #365 from MeshJS/claude/mcp-permissions-preprod
QSchlegel Aug 13, 2026
94f118f
fix(homepage): stop the CTA rows and MCP card overflowing their conta…
QSchlegel Aug 13, 2026
5b572e4
Merge pull request #366 from MeshJS/claude/mcp-cta-overflow
QSchlegel Aug 13, 2026
8c5b517
fix(mcp): make every scope reachable, and let the user pick which to …
QSchlegel Aug 13, 2026
5265634
Merge pull request #367 from MeshJS/claude/mcp-consent-scopes
QSchlegel Aug 13, 2026
dd5c35c
feat(governance): implement txGovernance API for per-transaction gove…
Andre-Diamond Aug 13, 2026
9e7957e
feat: enhance transaction flow visualization by splitting external ad…
Andre-Diamond Aug 13, 2026
123c01f
Merge remote-tracking branch 'origin/preprod' into feat/sign-off-tx-v…
Andre-Diamond Aug 13, 2026
dfa0e92
Merge pull request #368 from MeshJS/feat/sign-off-tx-visualization
Andre-Diamond Aug 13, 2026
111d970
fix: ensure serializedScript function handles missing scriptCbor corr…
Andre-Diamond Aug 14, 2026
d2c63af
feat: add support for repo-specific npm version in CI workflows and e…
Andre-Diamond Aug 14, 2026
b7074e2
fix: update jest mock configuration for applyRateLimit in txGovernanc…
Andre-Diamond Aug 14, 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
  •  
  •  
  •  
15 changes: 15 additions & 0 deletions .agents/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,22 @@ Specs live in the vault, not this repo. The maintainer keeps a document-driven d
- **OpenAPI**: `GET /api/swagger` (JSON).
- **Bot auth**: `POST /api/v1/botAuth` with body `{ "botKeyId", "secret", "paymentAddress" }` → `{ "token", "botId" }`. Use token as Bearer for `walletIds`, `pendingTransactions`, `freeUtxos`, `addTransaction`, `signTransaction`, etc. Reference client: `scripts/bot-ref/` (see README there).

## MCP (AI agents)

- **Endpoint**: `POST /api/mcp` — a stateless Model Context Protocol server built on
`@modelcontextprotocol/server` v2. Docs: `src/pages/api/mcp/README.md`.
- **Surface**: read-only plus governance ballot drafts. It cannot sign, spend or
broadcast, and that boundary is enforced by a test (`src/__tests__/mcpTools.test.ts`) —
adding a write tool must be a deliberate decision, not a registry addition.
- **Tools wrap the existing v1 handlers in-process** via `src/lib/mcp/invokeV1.ts`, so
authorization and validation stay defined once. Handler imports in
`src/lib/mcp/tools.ts` must stay **lazy** or the Mesh/whisky WASM lands in the route's
cold path.
- **Auth**: an OAuth 2.1 access token, or an existing v1 bearer token. The authorization
server lives under `src/pages/api/oauth/` — see `src/pages/api/oauth/README.md`.

## Docs to keep in sync

- Landing “Developers & Bots” section: `src/components/pages/homepage/index.tsx` (id `#developers-and-bots`).
- API/bot docs: `src/utils/swagger.ts`, `scripts/bot-ref/README.md`.
- MCP/OAuth: `src/pages/api/mcp/README.md`, `src/pages/api/oauth/README.md`.
1 change: 0 additions & 1 deletion .claude/worktrees/peaceful-northcutt
Submodule peaceful-northcutt deleted from 0d5ee8
10 changes: 8 additions & 2 deletions .cursor/skills/multisig/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,15 @@ description: Build and integrate with the Mesh Multisig (Cardano multisig wallet
## Bot integration (machine-friendly)

- **OpenAPI spec (JSON)**: `GET /api/swagger` — use for codegen or automation.
- **Registration (new bots)**: `POST /api/v1/botRegister`
Body: `{ "name": string, "requestedScopes": string[], "paymentAddress"?: string }`
New bots should initially register **without** `paymentAddress` — a fresh bot has no wallet yet. Register with just name + scopes, have the owner claim you, pick up your credentials, generate a wallet, then bind the address at first `botAuth`. Only pass `paymentAddress` at registration if the bot already controls a wallet.
- **Auth (bots)**: `POST /api/v1/botAuth`
Body: `{ "botKeyId": string, "secret": string, "paymentAddress": string, "stakeAddress"?: string }`
Response: `{ "token": string, "botId": string }`. Use `Authorization: Bearer <token>` for v1 endpoints.
Body: `{ "botKeyId": string, "secret": string, "paymentAddress"?: string, "stakeAddress"?: string }`
Response: `{ "token": string, "botId": string }`. Use `Authorization: Bearer <token>` for v1 endpoints. The first successful `botAuth` binds `paymentAddress` to the bot (required then; creates its `BotUser` if registration was address-less). Afterwards `paymentAddress` is optional — the JWT always carries the server-side bound address, and a mismatching supplied address is rejected (409). The token lives ~1 hour: cache it and re-auth on 401; the `secret` is picked up once via `botPickupSecret` but stays valid for repeated auths — store it safely.
- **Ballot drafting lifecycle (bots)**: `POST /api/v1/botBallotsUpsert` (drafts; proposalIds validated against the chain; response has `created` + `ballot.id`), `GET /api/v1/botBallots?walletId=` (reconcile your drafts), `DELETE /api/v1/botBallots` with `{walletId, ballotId}` (clean up stale drafts). All need `ballot:write` scope + any wallet grant (observer is enough). `GET /api/v1/botMe` returns `botWallets` (grants + roles) for self-discovery; `POST /api/v1/botRotateSecret` with the current secret mints a replacement if it leaks.
- **Rate-limit etiquette (bots)**: requests are limited per IP and per bot (default 40/min). Don't fan out in parallel — space calls ~200–500 ms apart. Responses carry `X-RateLimit-Remaining`/`X-RateLimit-Reset`; a 429 carries `Retry-After` (seconds) — wait that long (the reference client's `fetchWithBackoff` in `scripts/bot-ref/bot-client.ts` does this). Rejected requests never extend the window.
- **Governance reads (bots)**: `GET /api/v1/governanceActiveProposals?details=true` — use `details=true` to get `expiration` (voting-deadline epoch) and `deposit`; the response's `currentEpoch` gives time-to-deadline. "Active" = no terminal epoch on-chain; explorers may show a higher "active" count because they still display ratified-but-not-enacted actions — pass `includeRatified=true` to include those (status `ratified`, outcome already decided).
- **Bot keys**: Created in-app (User → Create bot). One bot key can have one `paymentAddress`; same address cannot be used by another bot.
- **Scopes**: Bot keys have scope (e.g. `multisig:read`); `botAccess.ts` enforces wallet access for bots.
- **V1 endpoints used by bots**: `walletIds` (query `address` = bot’s `paymentAddress`), `pendingTransactions`, `freeUtxos`, `addTransaction`, `signTransaction`, etc. Same as wallet-authenticated calls but identity is the bot’s registered address.
Expand Down
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ Thumbs.db
# Documentation
*.md
!README.md
# The feature vault is data, not documentation: /roadmap/graph reads these notes
# at runtime, so they have to survive the *.md filter above. Keep this as the
# bare directory — Railpack turns each negation into a literal copy instruction,
# and a `!vault/**` glob becomes `copy /vault/** /app/**`, which buildkit rejects
# with "cannot copy to non-directory". `!vault` alone copies the tree recursively.
!vault
docs

# Docker
Expand Down
18 changes: 18 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,21 @@ NEXT_PUBLIC_BLOCKFROST_API_KEY_PREPROD="your-blockfrost-preprod-api-key"
# DISCORD_CLIENT_SECRET="your-discord-client-secret"
# DISCORD_BOT_TOKEN="your-discord-bot-token"
# DISCORD_GUILD_ID="your-discord-guild-id"

# Optional: Email notifications via Resend
# RESEND_API_KEY="re_..."
# EMAIL_FROM="Mesh Multisig <notifications@your-domain.example>"
# EMAIL_REPLY_TO="support@your-domain.example"
# Optional: override notification email links. Required for localhost links when
# using `next start` locally (NODE_ENV is production). Defaults to
# http://localhost:3000 in `next dev` and the production site URL otherwise.
# NOTIFICATION_LINK_BASE_URL="http://localhost:3000"
# NOTIFICATION_DRAIN_SECRET="your-notification-drain-secret"
# NOTIFICATIONS_EMAIL_ENABLED="false"
# Optional: OAuth 2.1 issuer for the MCP endpoint (/api/mcp)
# Canonical origin of the authorization server. Access tokens carry it as `iss`,
# and the /.well-known discovery documents are built from it. Falls back to
# NEXT_PUBLIC_SITE_URL; set this only if the issuer must differ from the site
# origin. In non-production it falls back to the request host, so a local
# `next start` on any port works without setting anything.
# OAUTH_ISSUER_URL="https://multisig.meshjs.dev"
3 changes: 3 additions & 0 deletions .github/workflows/ci-smoke-preprod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
with:
node-version: 22

- name: Use repo npm version
run: npm install -g "$(node -p 'require("./package.json").packageManager')" && npm --version

- name: Check secrets configured
id: check-secrets
run: |
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/deploy-migrations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ jobs:
with:
node-version: '22'
cache: 'npm'


- name: Use repo npm version
run: npm install -g "$(node -p 'require("./package.json").packageManager')" && npm --version

- name: Install dependencies
run: npm ci

Expand Down
49 changes: 49 additions & 0 deletions .github/workflows/notification-outbox-drain.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Notification Outbox Drain

# Drains the notification outbox (pending + due-for-retry deliveries) by calling
# the authenticated drain endpoint. Requires NOTIFICATION_DRAIN_SECRET to be set
# both as a GitHub Actions secret and as an env var on the deployment; until
# both exist, runs are graceful no-ops.

on:
schedule:
# Every 15 minutes; the shortest retry delay in the worker is 5 minutes.
- cron: '*/15 * * * *'
# Allow manual triggering for testing
workflow_dispatch:

jobs:
drain:
runs-on: ubuntu-latest
timeout-minutes: 5

steps:
- name: Drain notification outbox
env:
API_BASE_URL: 'https://multisig.meshjs.dev'
DRAIN_SECRET: ${{ secrets.NOTIFICATION_DRAIN_SECRET }}
run: |
if [ -z "$DRAIN_SECRET" ]; then
echo "NOTIFICATION_DRAIN_SECRET repo secret is not set; skipping."
exit 0
fi

status=$(curl -s -o response.json -w "%{http_code}" -X POST \
"$API_BASE_URL/api/notifications/drain?limit=100" \
-H "Authorization: Bearer $DRAIN_SECRET")

echo "HTTP $status"
cat response.json || true
echo

case "$status" in
200)
;;
503)
echo "Drain endpoint reports NOTIFICATION_DRAIN_SECRET is not configured on the deployment; skipping."
;;
*)
echo "Drain request failed."
exit 1
;;
esac
3 changes: 3 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ jobs:
node-version: 22
cache: 'npm'

- name: Use repo npm version
run: npm install -g "$(node -p 'require("./package.json").packageManager')" && npm --version

- name: Install dependencies
run: npm ci

Expand Down
39 changes: 34 additions & 5 deletions .github/workflows/pr-multisig-v1-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ on:
default: ""
type: string

# Serialize against the Playwright e2e workflow: both broadcast from the same
# preprod CI wallets, so they must never run at the same time. A constant group
# (not per-PR) ensures mutual exclusion across PRs too. cancel-in-progress:false
# means runs queue rather than cancel each other.
concurrency:
group: ci-preprod-wallets
cancel-in-progress: false

jobs:
multisig-v1-smoke:
if: github.repository == 'MeshJS/multisig'
Expand All @@ -53,7 +61,23 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

# Dependabot-triggered runs never receive repo Actions secrets. When no
# core secret is present at all, skip the smoke instead of failing so
# dependabot PRs are not systematically red. A partial secret set still
# fails loudly in the validate step below.
- name: Check CI secrets configured
id: check-secrets
shell: bash
run: |
if [[ -z "$CI_JWT_SECRET" && -z "$CI_MNEMONIC_1" && -z "$CI_MNEMONIC_2" && -z "$CI_MNEMONIC_3" && -z "$CI_BLOCKFROST_PREPROD_API_KEY" ]]; then
echo "configured=false" >> "$GITHUB_OUTPUT"
echo "Multisig v1 smoke skipped: CI_* secrets not available to this run (e.g. dependabot-triggered)."
else
echo "configured=true" >> "$GITHUB_OUTPUT"
fi

- name: Validate required CI secrets
if: steps.check-secrets.outputs.configured == 'true'
shell: bash
run: |
missing=()
Expand Down Expand Up @@ -91,23 +115,27 @@ jobs:
fi

- name: Pull base image (with retry)
if: steps.check-secrets.outputs.configured == 'true'
shell: bash
run: |
for i in 1 2 3; do
docker pull node:20-alpine && break
docker pull node:22-slim && break
echo "Pull attempt $i failed, retrying in 30s..."
sleep 30
done

- name: Build CI containers
if: steps.check-secrets.outputs.configured == 'true'
shell: bash
run: docker compose -f docker-compose.ci.yml build

- name: Start Postgres + App containers
if: steps.check-secrets.outputs.configured == 'true'
shell: bash
run: docker compose -f docker-compose.ci.yml up -d postgres app

- name: Wait for app healthcheck
if: steps.check-secrets.outputs.configured == 'true'
shell: bash
run: |
for i in {1..60}; do
Expand All @@ -124,11 +152,12 @@ jobs:
exit 1

- name: Run CI wallet bootstrap + v1 route-chain smoke
if: steps.check-secrets.outputs.configured == 'true'
shell: bash
run: docker compose -f docker-compose.ci.yml --profile ci-test run --rm ci-runner

- name: Dump container logs on failure
if: failure()
if: failure() && steps.check-secrets.outputs.configured == 'true'
shell: bash
run: |
docker compose -f docker-compose.ci.yml logs --no-color \
Expand All @@ -145,22 +174,22 @@ jobs:
> docker-compose-ci.log

- name: Upload logs on failure
if: failure()
if: failure() && steps.check-secrets.outputs.configured == 'true'
uses: actions/upload-artifact@v4
with:
name: docker-compose-ci-logs
path: docker-compose-ci.log

- name: Upload route-chain report
if: always()
if: always() && steps.check-secrets.outputs.configured == 'true'
uses: actions/upload-artifact@v4
with:
name: ci-route-chain-report
path: ci-artifacts/ci-route-chain-report.md
if-no-files-found: warn

- name: Tear down CI containers
if: always()
if: always() && steps.check-secrets.outputs.configured == 'true'
shell: bash
run: docker compose -f docker-compose.ci.yml down -v --remove-orphans

Loading
Loading