app spec: the answers from the app repo, and alpha caught up
three questions answered from monorepo-mobile, and two of my assumptions were wrong. bundle ids exist — dev.officer.mobile and dev.officer.mobile.dev. two of them needs nothing special: push_devices is unique on (token, bundleId), so the variants are separate rows on one phone, and the dev variant is exactly the sandbox/production distinction the doc warned about. concrete now rather than derived from build config by guesswork. scheme is officer:// and officer-dev://, both from app.config.ts. expo prebuild, not bare — and a config plugin that creates an ios app extension target ALREADY EXISTS there, withVaultAutofillTarget.js for the autofill extension. the nse follows it. that removes what i had called the longest pole in phase 3. corrected: expo-notifications is not in apps/mobile at all, only apps/chat. the real blocker is narrower than the doc implied and is not code. today's signed build has no aps-environment entitlement, and adding one fails while xcode has no account signed in — same failure as the network extension on 2026-08-05. one manual sign-in, team RGHC4NJC77, then automatic again. alpha: /api/notify was 404 all day because that server predated the work. pulled, db:push, gen:ecosystem, officer-notify started, officer restarted. verified 401 unauthenticated and push_devices with its 10 columns.
This commit is contained in:
@@ -15,6 +15,11 @@ the build order, and it does not repeat the reasoning.
|
||||
`{"ok":true,"channels":[]}` and every send is a silent no-op that returns success. **A green response
|
||||
does not mean a push was sent** — check `channels` first, or you will debug the app for a day over a
|
||||
server with no key.
|
||||
- **Alpha is up to date as of 2026-08-19 19:xx.** `/api/notify/*` answered `404` there for most of the day
|
||||
because the server predated this work; it now answers `401` unauthenticated, `push_devices` has its 10
|
||||
columns, and `officer-notify` is running. If you get a `404`, that server needs `git pull` +
|
||||
`pm2 restart officer`, and `officer-notify` needs starting — it is a new core process, so an existing
|
||||
install will not have it until `bun gen:ecosystem` runs.
|
||||
|
||||
## Which app
|
||||
|
||||
@@ -31,7 +36,7 @@ work, nothing later will, and everything later is harder to debug.
|
||||
|
||||
### 1. iOS project setup
|
||||
|
||||
- A bundle id for `apps/mobile` (only `dev.officer.music` was ever confirmed to exist — check).
|
||||
- A bundle id for `apps/mobile` — **confirmed: `dev.officer.mobile`**, plus `dev.officer.mobile.dev`.
|
||||
- `aps-environment` entitlement. Do **not** copy chat's plugin here; the hub needs the opposite.
|
||||
- Push capability on the App ID in the developer portal, and a provisioning profile that includes it.
|
||||
|
||||
@@ -143,14 +148,15 @@ longer installed and stop.
|
||||
**One build, ever.** The extension is a generic resolver — it must never `switch` on known codes, or every
|
||||
new notification kind becomes an app store release, which is the entire thing this design exists to avoid.
|
||||
|
||||
Note for Expo: a custom NSE needs a config plugin (`expo-notifications` alone does not give you one). Worth
|
||||
scoping early — it may be the longest pole in Phase 3.
|
||||
Expo: `ios/` is generated by prebuild, so the NSE target comes from a config plugin. **One already exists
|
||||
in this repo** — `packages/bw-vault/plugin/withVaultAutofillTarget.js` creates the AutoFill extension
|
||||
target. Follow it rather than inventing one.
|
||||
|
||||
## Phase 4 — deep linking
|
||||
|
||||
`route` from the mapping is the destination. Tapping a notification opens the hub, which routes onward to
|
||||
the target app or screen. Confirm the scheme with the owner — the platform uses `officer://<hex>` origins
|
||||
for app surfaces, and I have not verified what `apps/mobile` registers today.
|
||||
the target app or screen. The scheme is **`officer://`** (`officer-dev://` in the dev variant), from
|
||||
`app.config.ts`.
|
||||
|
||||
## Android — later, but design for it now
|
||||
|
||||
@@ -177,8 +183,37 @@ Android build and is not yours to absorb.
|
||||
- **`appSlug` means the deep-link destination**, not "which app receives this". The name is a leftover from
|
||||
the first design, where each app had its own token.
|
||||
|
||||
## Open questions for the owner
|
||||
## Answered, from the app repo (2026-08-19)
|
||||
|
||||
1. Does `apps/mobile` have a bundle id and a provisioning profile with push enabled?
|
||||
2. What URL scheme does `apps/mobile` register for deep links?
|
||||
3. Is the hub in Expo managed or bare? It decides how the NSE gets built.
|
||||
**Bundle ids exist.** `dev.officer.mobile`, and `dev.officer.mobile.dev` for the side-by-side dev variant.
|
||||
Two bundle ids is fine and needs nothing special: `push_devices` is unique on `(token, bundleId)`, so the
|
||||
two variants register as separate rows on the same phone. **Register the dev variant as
|
||||
`environment: "sandbox"` and production as `"production"`** — that mapping is now concrete, so derive it
|
||||
from the variant rather than the build config guesswork this document suggested earlier.
|
||||
|
||||
**The URL scheme is `officer://`, and `officer-dev://` in the dev variant.** Both come from
|
||||
`app.config.ts`, and the share extension embeds the same string natively, so they cannot desync. So the
|
||||
unknown-code fallback deep link is `officer://resync-notification-mapping` as written.
|
||||
|
||||
**Expo prebuild (CNG), not bare** — `ios/` is generated and gitignored; everything native comes from config
|
||||
plugins. This is better news than the document assumed: **a config plugin that creates an iOS app-extension
|
||||
target already exists in this repo**, `packages/bw-vault/plugin/withVaultAutofillTarget.js`, which builds
|
||||
the AutoFill extension that prebuild cannot. **The NSE follows that pattern rather than being invented**,
|
||||
which removes what this document called the longest pole in Phase 3.
|
||||
|
||||
**`expo-notifications` is NOT in `apps/mobile`** — only in `apps/chat`, for local turn alerts. Correcting
|
||||
this document's assumption. Chat's `withoutPushEntitlement.js` still stays exactly as described above; the
|
||||
hub needs the opposite.
|
||||
|
||||
## The one real blocker: the push entitlement
|
||||
|
||||
Today's signed build (`2026.08.19.02`) has **no `aps-environment` entitlement at all**. Nothing else in
|
||||
Phase 1 can be tested until it does.
|
||||
|
||||
It has a known shape here. On 2026-08-05 adding a Network Extension failed for the same reason:
|
||||
`-allowProvisioningUpdates` **cannot add a capability while Xcode has no account signed in**. The fix is a
|
||||
one-time manual step by the owner — Xcode → Settings → Accounts, team `RGHC4NJC77` — after which it is
|
||||
automatic again.
|
||||
|
||||
**Owner action, and it is the critical path.** Along with the APNs `.p8`, this is the whole of what stands
|
||||
between here and a banner on a phone.
|
||||
|
||||
Reference in New Issue
Block a user