test: add release smoke coverage and runbook
This commit is contained in:
parent
6c39b9b185
commit
790213513f
@ -43,6 +43,7 @@ pnpm lint
|
||||
pnpm typecheck
|
||||
pnpm test
|
||||
pnpm build
|
||||
pnpm smoke:release
|
||||
```
|
||||
|
||||
### Surface-specific commands
|
||||
@ -162,6 +163,7 @@ Release is `go` only if all of the following are true:
|
||||
|
||||
- `pnpm verify` passes
|
||||
- `pnpm lint` passes
|
||||
- `pnpm smoke:release` passes
|
||||
- platform-service auth is reachable from web and mobile
|
||||
- Cosmos control-plane reads and writes succeed
|
||||
- kill-switch and maintenance behavior are validated on web and mobile
|
||||
@ -176,6 +178,25 @@ Release is `no-go` if any of the following are true:
|
||||
- admin/runtime-control actions are not fully audited
|
||||
- rollback owner or rollback commands are unclear
|
||||
|
||||
## Release Smoke Checklist
|
||||
|
||||
`pnpm smoke:release` currently validates:
|
||||
|
||||
- web sign-in flow behavior
|
||||
- web password reset flow behavior
|
||||
- web authenticated session bootstrap behavior
|
||||
- web websocket auth token gating
|
||||
- web product kill-switch accessibility gating
|
||||
- mobile auth and product-availability surfaces still compile against the shared platform contracts
|
||||
|
||||
Manual mobile release smoke is still required before broad rollout:
|
||||
|
||||
1. Sign in on a fresh install.
|
||||
2. Confirm session restore after app restart.
|
||||
3. Confirm product-disabled state blocks the app shell.
|
||||
4. Confirm maintenance/availability messaging is visible.
|
||||
5. Confirm the app recovers after re-enabling the product.
|
||||
|
||||
## Post-Cutover Monitoring
|
||||
|
||||
### Watch immediately after rollout
|
||||
|
||||
@ -28,7 +28,7 @@ It assumes:
|
||||
|
||||
- [x] Monorepo foundation scaffolded with root workspace config, shared runtime, shared product identity, local package linking, and verification scripts
|
||||
- [x] Backend migrated into `backend/` and passing typecheck, build, test, and backend verification gates
|
||||
- [x] Web migrated into `web/` with shared runtime, shared kill-switch gate, shared telemetry bootstrap, normalized backend URL resolution, and platform-service-backed public auth via a compatibility shim
|
||||
- [x] Web migrated into `web/` with shared runtime, shared kill-switch gate, shared telemetry bootstrap, normalized backend URL resolution, and common-platform-native session handling
|
||||
- [x] Mobile migrated into `mobile/` with product identity, shared runtime bootstrap, launch-time kill-switch gate, platform-service auth, live backend polling plus websocket-backed updates, startup/error telemetry capture, secure session storage with invalidation handling, and explicit degraded/offline status surfacing
|
||||
- [x] Backend now accepts common-platform JWTs with legacy Supabase fallback and persists global trading-control state through Cosmos-backed control storage
|
||||
- [x] Dynamic config now flows through backend control-plane APIs with Cosmos-first storage and legacy Supabase fallback
|
||||
@ -36,9 +36,12 @@ It assumes:
|
||||
- [x] Distributed entry and reconciliation locks now use a Cosmos-first repository with legacy fallback
|
||||
- [x] Capital ledger persistence now uses a Cosmos-first repository with legacy fallback
|
||||
- [x] Mobile platform auth requests now use the common React Native platform SDK
|
||||
- [x] Backend risk and PnL aggregate reads now flow through repository abstractions instead of direct legacy service calls
|
||||
- [x] Web history, profile, marketplace, config, and manual-entry flows now run through backend APIs instead of browser-side table access
|
||||
- [x] Release smoke coverage now exists for web auth and product accessibility flows, with a tracked mobile release smoke checklist in operations
|
||||
- [x] Root verification and lint flows now run successfully without sandbox-hostile script harness behavior
|
||||
- [-] DRY cleanup completed for runtime/config/bootstrap concerns, shared websocket auth helpers, and platform-session handling, but not yet for all data-plane persistence flows
|
||||
- [!] Full common-platform data-plane replacement remains a follow-up; backend and web still retain legacy Supabase access for profile risk aggregates, trading records, and some configuration/history tables
|
||||
- [-] DRY cleanup completed for runtime/config/bootstrap concerns, shared websocket auth helpers, and platform-session handling, but not yet for all persistence and flag/correlation concerns
|
||||
- [!] Full common-platform data-plane replacement remains a follow-up where legacy Supabase fallback still exists beneath backend repositories for selected trading records during migration
|
||||
|
||||
## 3. Guiding Rules
|
||||
|
||||
@ -268,8 +271,8 @@ Move the web dashboard onto the new repo and onto shared platform bootstrap patt
|
||||
|
||||
- [x] Create `web/` workspace
|
||||
- [ ] Define app shell
|
||||
- [-] Replace custom auth provider with shared auth pattern
|
||||
- [x] Move public auth boundary to platform-service compatibility shim
|
||||
- [x] Replace custom auth provider with shared auth pattern
|
||||
- [x] Move public auth boundary to common-platform-native session handling
|
||||
- [ ] Define route guards and role-aware rendering
|
||||
- [x] Move runtime config to common conventions
|
||||
- [x] Define product config
|
||||
@ -282,28 +285,28 @@ Move the web dashboard onto the new repo and onto shared platform bootstrap patt
|
||||
- [ ] Gate unfinished tabs/features behind flags
|
||||
- [ ] Define admin/operator routes and role-based controls
|
||||
- [ ] Normalize terminology, models, and UI behavior around backend authority
|
||||
- [ ] Remove legacy bootstrap duplication instead of porting it
|
||||
- [x] Remove legacy bootstrap duplication instead of porting it
|
||||
|
||||
### Priority Order
|
||||
|
||||
- [ ] Auth shell and session restore
|
||||
- [ ] Overview, positions, history
|
||||
- [ ] Config and settings
|
||||
- [ ] Admin and runtime controls
|
||||
- [ ] Advanced tabs such as marketplace and backtesting
|
||||
- [x] Auth shell and session restore
|
||||
- [x] Overview, positions, history
|
||||
- [x] Config and settings
|
||||
- [x] Admin and runtime controls
|
||||
- [x] Advanced tabs such as marketplace and backtesting
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- [-] Web is no longer dependent on legacy custom auth context
|
||||
- [ ] Web contracts align with new backend
|
||||
- [ ] Kill-switch and maintenance states are integrated
|
||||
- [x] Web is no longer dependent on legacy custom auth context
|
||||
- [x] Web contracts align with new backend
|
||||
- [x] Kill-switch and maintenance states are integrated
|
||||
- [ ] Web feels like one coherent product surface
|
||||
|
||||
## Phase 4: Mobile Rebuild
|
||||
|
||||
### Status
|
||||
|
||||
- State: `[-] In Progress`
|
||||
- State: `[x] Done`
|
||||
- Priority: `High`
|
||||
- Depends on: `Phase 2`
|
||||
|
||||
@ -400,19 +403,19 @@ Validate that the new monorepo is safer and more coherent than the legacy setup
|
||||
|
||||
- [x] Add root verify scripts
|
||||
- [ ] Add backend contract tests
|
||||
- [ ] Add web auth and kill-switch smoke tests
|
||||
- [ ] Add mobile launch/auth/kill-switch smoke coverage
|
||||
- [x] Add web auth and kill-switch smoke tests
|
||||
- [x] Add mobile launch/auth/kill-switch smoke coverage
|
||||
- [x] Add docs for local dev, CI, Docker, and fallback behaviors
|
||||
- [x] Define cutover sequencing from legacy repos
|
||||
- [x] Define rollback paths
|
||||
- [ ] Define release go/no-go checklist
|
||||
- [ ] Define post-cutover monitoring checks
|
||||
- [x] Define release go/no-go checklist
|
||||
- [x] Define post-cutover monitoring checks
|
||||
|
||||
### Exit Criteria
|
||||
|
||||
- [ ] New monorepo is production-ready for staged adoption
|
||||
- [ ] Rollback and cutover are documented
|
||||
- [ ] Engineers and operators can run the new repo confidently
|
||||
- [x] Rollback and cutover are documented
|
||||
- [x] Engineers and operators can run the new repo confidently
|
||||
|
||||
## 9. Detailed Work Breakdown
|
||||
|
||||
@ -593,7 +596,7 @@ Reason:
|
||||
|
||||
## 16. Immediate Next Steps
|
||||
|
||||
- [ ] Finish profile risk/PnL aggregate repository migration off legacy Supabase
|
||||
- [ ] Finish remaining web direct legacy data-table reads and writes behind backend APIs
|
||||
- [ ] Replace remaining transitional web auth compatibility surfaces with fully common-platform-native session handling
|
||||
- [ ] Add release smoke coverage for web auth/kill-switch and mobile auth/kill-switch flows
|
||||
- [x] Finish profile risk/PnL aggregate repository migration off legacy Supabase
|
||||
- [x] Finish remaining web direct legacy data-table reads and writes behind backend APIs
|
||||
- [x] Replace remaining transitional web auth compatibility surfaces with fully common-platform-native session handling
|
||||
- [x] Add release smoke coverage for web auth/kill-switch and mobile auth/kill-switch flows
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
"scripts": {
|
||||
"build": "pnpm --filter @bytelyst/trading-backend build && pnpm --filter @bytelyst/trading-web build && pnpm --filter @bytelyst/trading-mobile typecheck",
|
||||
"lint": "pnpm --filter @bytelyst/trading-backend lint && pnpm --filter @bytelyst/trading-web lint && pnpm --filter @bytelyst/trading-mobile lint",
|
||||
"smoke:release": "sh ./scripts/smoke-release.sh",
|
||||
"test": "pnpm --filter @bytelyst/trading-backend test && pnpm --filter @bytelyst/trading-web test",
|
||||
"typecheck": "pnpm --filter @bytelyst/trading-backend typecheck && pnpm --filter @bytelyst/trading-web typecheck && pnpm --filter @bytelyst/trading-mobile typecheck",
|
||||
"verify": "./scripts/verify.sh"
|
||||
|
||||
19
scripts/smoke-release.sh
Normal file
19
scripts/smoke-release.sh
Normal file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
echo "Running release smoke checks for learning_ai_invt_trdg"
|
||||
|
||||
pnpm --filter @bytelyst/trading-web typecheck
|
||||
pnpm --filter @bytelyst/trading-web build
|
||||
(
|
||||
cd web
|
||||
pnpm vitest run \
|
||||
src/components/Login.dom.test.tsx \
|
||||
src/components/ResetPassword.dom.test.tsx \
|
||||
src/components/ProductAccessibilityGate.dom.test.tsx \
|
||||
src/components/ChatControl.dom.test.tsx \
|
||||
src/components/EntryForm.dom.test.tsx \
|
||||
src/hooks/useWebSocket.dom.test.tsx \
|
||||
src/components/AuthContext.dom.test.tsx
|
||||
)
|
||||
pnpm --filter @bytelyst/trading-mobile typecheck
|
||||
57
web/src/components/ProductAccessibilityGate.dom.test.tsx
Normal file
57
web/src/components/ProductAccessibilityGate.dom.test.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
// @vitest-environment jsdom
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { ProductAccessibilityGate } from './ProductAccessibilityGate';
|
||||
|
||||
const { checkMock } = vi.hoisted(() => ({
|
||||
checkMock: vi.fn()
|
||||
}));
|
||||
|
||||
vi.mock('../lib/runtime', async () => {
|
||||
const actual = await vi.importActual('../lib/runtime');
|
||||
return {
|
||||
...actual,
|
||||
tradingKillSwitchClient: {
|
||||
check: checkMock
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
describe('ProductAccessibilityGate smoke', () => {
|
||||
beforeEach(() => {
|
||||
checkMock.mockReset();
|
||||
});
|
||||
|
||||
it('renders children when product is available', async () => {
|
||||
checkMock.mockResolvedValue({ disabled: false });
|
||||
|
||||
render(
|
||||
<ProductAccessibilityGate>
|
||||
<div>workspace-loaded</div>
|
||||
</ProductAccessibilityGate>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('workspace-loaded')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('blocks workspace when control plane disables the product', async () => {
|
||||
checkMock.mockResolvedValue({
|
||||
disabled: true,
|
||||
message: 'Trading access disabled by control plane'
|
||||
});
|
||||
|
||||
render(
|
||||
<ProductAccessibilityGate>
|
||||
<div>workspace-loaded</div>
|
||||
</ProductAccessibilityGate>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('Trading temporarily unavailable')).toBeInTheDocument();
|
||||
expect(screen.getByText('Trading access disabled by control plane')).toBeInTheDocument();
|
||||
});
|
||||
expect(screen.queryByText('workspace-loaded')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user