Skip to content

Runbook: Riff #165 — admin-console workspace dep + POC migration

Status: ready to execute. Operator-gated on sudo chown. Tracks: Riff #165. Effort: ~10 min operator + ~10 min for the code patch + verify. Prerequisite: admin-console node_modules is root-owned (legacy Docker mount). npm install fails with "operation rejected by your operating system."

Why

Plan #026 Slice J shipped the generated-client-type POC in partner-console (payment.service.ts uses satisfies keyof PaymentPaths for typed URL templates). The admin-console half stayed deferred because we couldn't npm install @po/contracts over root-owned node_modules.

This runbook unblocks it.

Steps

1. Fix the directory ownership (one command)

sudo chown -R "$USER:$USER" frontends/admin-console/node_modules
# OR — if you'd rather wipe + reinstall (safer if the existing tree
# has half-installed bits from past docker volume mounts):
sudo rm -rf frontends/admin-console/node_modules

2. Wire the workspace dep into admin-console

Edit frontends/admin-console/package.json — add the entry in dependencies (alphabetical):

   "dependencies": {
     "@hookform/resolvers": "^5.2.2",
+    "@po/contracts": "file:../../packages/contracts",
     "@radix-ui/react-collapsible": "^1.1.12",

3. Reinstall

cd frontends/admin-console
npm install

This regenerates package-lock.json to include @po/contracts. Both files (package.json + lockfile) get committed.

4. Apply the POC migration to payment.service.ts

The pattern is identical to frontends/partner-console/src/services/payment.service.ts:

 import { getPaymentServiceUrl } from '@/utils/domain-detector';
 import { apiClient } from '@/utils/api-client';
+import type { paths as PaymentPaths } from '@po/contracts/clients/payment-service/types';

 const API_BASE = getPaymentServiceUrl();
+
+/**
+ * Plan #026 Slice J — generated-spec consumption POC (admin-console half).
+ *
+ * URL constants are typed against the generated `PaymentPaths` keys, so
+ * any rename / deletion of the upstream route fails `tsc --noEmit` at
+ * build time. `keyof PaymentPaths` is the source of truth.
+ */
+const REFUNDS_LIST_PATH =
+  '/payments/refunds' satisfies keyof PaymentPaths;
+const REFUND_BY_ID_PATH =
+  '/payments/refunds/{id}' satisfies keyof PaymentPaths;
+const TRANSFERS_LIST_PATH =
+  '/payments/transfers' satisfies keyof PaymentPaths;
+const TRANSFER_REVERSAL_PATH =
+  '/payments/transfers/{id}/reversal' satisfies keyof PaymentPaths;
+const DISPUTES_LIST_PATH =
+  '/payments/disputes' satisfies keyof PaymentPaths;
+const DISPUTE_BY_ID_PATH =
+  '/payments/disputes/{id}' satisfies keyof PaymentPaths;

Then update each URL builder in the service object:

-    const url = `${API_BASE}/payments/refunds${buildQuery(filters)}`;
+    const url = `${API_BASE}${REFUNDS_LIST_PATH}${buildQuery(filters)}`;

Repeat for the 7 URL constructions (listRefunds, getRefund, createRefund, listTransfers, reverseTransfer, listDisputes, getDispute) — see frontends/admin-console/src/services/payment.service.ts:174-252 for current literals.

5. Extend the test

In frontends/admin-console/src/pages/PaymentsPage.test.tsx (or wherever the smoke covering the service lives), add the type-safety assertion:

import type { paths as PaymentPaths } from '@po/contracts/clients/payment-service/types';

describe('payment.service URL constants', () => {
  it('all template paths satisfy keyof PaymentPaths', () => {
    // Compile-time guard — if any literal drifts from the generated spec,
    // tsc fails at this assertion. The runtime assertion is a smoke check.
    const _refunds: keyof PaymentPaths = '/payments/refunds';
    const _transfers: keyof PaymentPaths = '/payments/transfers';
    const _disputes: keyof PaymentPaths = '/payments/disputes';
    expect(_refunds).toBe('/payments/refunds');
    expect(_transfers).toBe('/payments/transfers');
    expect(_disputes).toBe('/payments/disputes');
  });
});

6. Verify

cd frontends/admin-console
npx tsc --noEmit       # must be clean
npm run lint           # must be clean
npm test               # PaymentsPage suite + new assertion green

7. Commit + push

cd ../..
git add frontends/admin-console/package.json \
        frontends/admin-console/package-lock.json \
        frontends/admin-console/src/services/payment.service.ts \
        frontends/admin-console/src/pages/PaymentsPage.test.tsx

git commit -m "[sA] chore(admin-console): Riff #165 — @po/contracts workspace dep + payment.service POC

Closes Plan #026 Slice J's deferred admin-console half. Same pattern
as partner-console payment.service.ts (commit 55c6e4f): URL constants
typed against generated PaymentPaths, so any upstream route rename
fails tsc at build time."
git push

8. Flip Riff #165done

After the pipeline goes green.

Rollback

If npm install errors after sudo chown, the chown can be reverted:

sudo chown -R root:root frontends/admin-console/node_modules

But there's no reason to — node_modules should never be root-owned on a dev laptop. The chown is the right state.

Cross-references

  • Riff #165: tasks-prod
  • Plan #026 retrospective: docs/implementation-plans/026-test-foundation-structural-hygiene/RETROSPECTIVE.md
  • partner-console POC reference: frontends/partner-console/src/services/payment.service.ts (commit 55c6e4f)
  • OpenAPI gate doc: docs/developers/api/openapi.md