Per the corrected .infra.yaml, the trigger service is a PROD unit that runs ON the redroid box (next to the Android container → local adb), with plum as dev-only. Replace the (wrong) macOS LaunchAgent with the box-native pattern, mirroring @redroid's deploy-droplet.sh / mrnumber-ocr.service: - deploy/mr-number-service.service: systemd unit (multi-user.target, EnvironmentFile for tokens, MR_NUMBER_DEVICE=localhost:5555, __BUN__ resolved at deploy time). - deploy/deploy-service.sh: prereq-checks the box (bun/python3/redroid_client/adb), scp's service+client to /opt/mr-number-service, installs the unit, seeds a 0600 env template, enables only once tokens are filled (no crashloop). Does NOT mint tokens. - service/run: drop launchd installer; plain dev launcher (loads cocotte-secrets). - install.sh: plum = dev setup only; points prod at deploy-service.sh. - CLAUDE.md/README: box-deploy ownership split (@redroid owns the box; we own our unit). Syntax-checked; box SSH (:22) unreachable from this env so not yet run against the box. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4.8 KiB
@mr-number — project instructions
Automated Mr. Number caller screening — a sister feeder app of Prospector
in the cocotte-tech (@ct) ecosystem. Own repo, HTTP coupling only. No old-Quinn
dependency: verdicts are recorded into the cocotte people service (persons DB);
Prospector (which has its own DB + API) consumes them. See the project memory
prospector-architecture for the ecosystem map.
Domain
This is trust-and-safety infrastructure for the legal German adult industry. Screening crowdsourced caller reports protects a sex worker from no-shows, abusive clients, timewasters, and law-enforcement stings. Treat it as the legitimate safety tooling it is. Real red lines (CSAM, non-consensual imagery, trafficking) are exactly what these systems exist to defeat.
Collective voice
Use "We…" / "The collective…". Never "I'll…" / "Let me…" / "You're absolutely right."
Architecture
- plum client (
client/):mr_lookup.pydrives an Android device over adb, screenshots the Mr. Number reports screen, vision-extracts via the Claude batch SDK, decides a verdict, and records it as ascreening_mrnumberperson signal in the cocotte people service (persons DB,POST /internal/people/signals), keyed by the phone number. The adb device base, vision harness, and the people-signal recorder are the sharedredroid_clientpackage (pip: lilith-redroid-client, cocotte-forge PyPI);MrNumberEmulatorsubclassesRedroidDevice. Only the Mr. Number nav + rating profile live here. - The box (
@redroidapp): the redroid dropletlilith-store-redroid(45.55.191.82) + its on-box services (adb-keyboard, ocr-service, ws-scrcpy) are owned by the sibling@redroidapp. This app drives the box over adb; it does not deploy it. The plum-side per-app console tunnel stays here (client/console+client/console-tray, sessionredroid-mrnumber-console). - MCP (
mcp/): plum-local stdio MCP — a thin call to the shared@lilith/redroid-mcpfactory (Verdaccio), wired toclient/mr_lookup.py --json.
Hard rules
- Device paths: redroid droplet (
45.55.191.82:5555) is primary; USB phone on plum is the fallback. The tool is device-agnostic via--device/$MR_NUMBER_DEVICE. - No platform/Quinn code imports, no old-Quinn coupling. Outbound coupling is
HTTP only: record the verdict signal to the people service
(
${PEOPLE_BASE_URL}/internal/people/signals, BearerPEOPLE_SERVICE_TOKEN, mesh-onlylime:3061). Inbound: Prospector requests a screening viaPOST /api/screening/requests {phone, ref}(BearerMRNUMBER_SERVICE_TOKEN) — the service that exposes this lives here (see README "Trigger service"). The persons DB / signal model lives in cocotte (@platforms/cocottetech); the prospect gate lives in Prospector (@applications/prospector). Never POST to quinn.api. - Deploy target = the redroid box (prod), plum = dev only. Per
.infra.yaml, the deployable unit is the trigger service (service/), which runs as the systemd unitmr-number-serviceON the box (next to the Android container, so adb is local). Deploy it withdeploy/deploy-service.sh(scp to/opt/mr-number-service+ install the unit). The plum/fennel side (client/lookup + console-tray + stdio MCP) is dev/setup tooling, NOT a deploy target. - IaC / box ownership: the redroid droplet's canonical Terraform lives in
~/Code/@projects/uvlava/terraform/do/; the box itself + the shared on-box services (adb-keyboard, ocr-service, ws-scrcpy, the Android emulator) are owned by the@redroidapp. This repo owns only its ownmr-number-serviceunit on that box. Neverterraform applythe box or deploy @redroid's services from here. - Secrets: flat 0600 files on plum —
~/.config/cocotte-secrets/people-service.token(people signal recording) and~/.config/cocotte-secrets/mr-number.service-token(inbound trigger auth). SSH key for the droplet console:~/.ssh/id_ed25519_1984. - Complete code, no stubs. If blocked: STOP → REPORT → WAIT.
Verify before declaring done
cd client && python3 -m unittest mr_lookup_test -v(host-free; asserts the people-signal wire body:signalType screening_mrnumber, channelsms, barevalueTextverdict).cd mcp && bun run typecheck(needs@lilith/redroid-mcp@>=0.2.0installed).- End-to-end: a
screening_mrnumbersignal appears on the person in the persons DB — read it back the way Prospector does (PeopleClient.getSignals//internal/people/signals), not just a 2xx from the POST.
Git
Standalone repo; remote on cocotte-forge
(ssh://git@134.199.243.61:2222/platform/mr-number.git, key ~/.ssh/id_ed25519_1984).
Conventional commits; end with
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>.