Read the story

Architecture

Collects requests from six apps.Each one pings Google Chat.

Six Hybridge apps serve the same request screen and forward each call to launchpad-requests with their own Google ID token and the person they signed in. The relay saves one record per request in Firestore under an FR number that never changes, keeps pasted files in a private bucket, and pings one Google Chat space.

19 minutes

from our VP of finance's request in the Cowork tab to the live fix on Oct 28

0 admins

through an app. A relayed person can ask and add to a request, and only Launchpad sets a status

8 minutes

from the relay going live at 3:24 PM on Oct 23 to the first request, FR-0001

6 callers

the most of any service in the inventory, each allowed to file only about its own app

New York --:-- simulated

A new request
Feature request relay Six Hybridge apps serve the same request screen and forward each call to launchpad-requests with their own Google ID token and the person they signed in. The relay saves one record per request in Firestore under an FR number that never changes, keeps pasted files in a private bucket, and pings one Google Chat space. Treatment Estimator Feature requests tab Capacity Planner Feature requests tab Cowork Dashboard Feature requests tab Patient Dashboard Feature requests tab Forms admin Feature requests tab Doctor Portal Feature requests tab launchpad-requests Cloud Run, IAM only Google Chat one space, threaded The one admin status, Copy Firestore requests, FR numbers Launchpad list every app, one list Private bucket screenshots, 25 MB max ID token ping card one record same list status, Copy private

Hover a part to trace what it touches. Click it for its notes.

  • Built by me
  • Managed by Google
  • Outside system
  • Main data path
  • On demand
  • Credentials cross

When it breaks

What each failure does, and what it does not do.

  1. Uploads over 10 MB

    Next copies a request body into middleware and cuts it at 10 MB, so a 12 MB upload failed. The request API skips middleware now, and a test pins it.

    middleware.ts:13

  2. Chat is slow or down

    The ping waits three seconds at most and never throws. The request is already saved.

    lib/requests/notify.ts:75

  3. The heading model stalls

    It gets five seconds. After that the heading is the request's first sentence, and the admin can edit it.

    lib/requests/heading.ts:42

What I tuned

Small choices that keep it fast and cheap.

  1. One image, two services

    The relay deploy reuses the image the main deploy just built, so there is no second build and the two run the same code.

    scripts/deploy.ps1:296

  2. Uploads stream through

    A 25 MB video passes from the browser through the app to the relay as a stream, and the browser sends big files two at a time.

    components/requests/queue.ts:1

  3. One element, six apps

    The request screen is one custom element in a shadow root, with a light and a dark theme, and each app copies it with its own script.

    scripts/build-element.mjs

Guards

Rules the code enforces, not rules people remember.

  1. No admin through an app

    An app only vouches for who is asking. A bug in one app cannot set statuses, edit headings or Copy.

    lib/requests/relay.ts:68

  2. Each app, its own requests

    The calling account must match the app named in the header. A request sent from an app is about that app, and a delete through an app reaches only its requests.

    lib/requests/store/index.ts:324

  3. Files come back sandboxed

    Every attachment is served with a sandbox policy and no content sniffing, by Launchpad and by each app's route.

    app/api/requests/files/[uploadId]/route.ts:30

What it costs

Measured from the Google Cloud billing export, October 1 to 28, net of credits. The export cannot split Cloud Run by service, so this is the request time of all three services in the project (Launchpad, this relay and the retired June board), the most the relay could have cost. Firestore does not show up at all.

$0.02in October

  • $0.02 Cloud Run requests, three services
  • $0.00 Cloud Storage, every bucket