# Let one required feature decide build versus buy

*Letting any AI assistant use HYVIRAL · Sign-in provider test. From the portfolio of Guilherme Rohden. Excerpts are quoted verbatim; internal paths and identifiers are redacted.*

The pass-or-fail rule written before the sign-in provider test, the results table, and the response that ruled the provider out: unsupported scope intel:read.

## The decision

Sign-in for outside assistants had to express what a connected assistant may do: HYVIRAL’s own permission scopes, a branded consent screen, client registration, and discovery metadata with tokens tied to the intended service.

I fixed a testable rule in advance: failure of any mandatory requirement meant building the authorization server in-house. A passing spike would keep the work on resource-server integration and consent branding. Either way, the external MCP contract stayed the same.

Building it in-house keeps HYVIRAL’s permission vocabulary and consent flow under my control, and makes protocol implementation, token handling and security review my engineering responsibility.

## From the source

**Authorization specification.** The decision rule, recorded as locked:

> *D10 · Locked*
>
> Phase 0 default rule: if **any** of the four AS requirements (custom scopes, branded consent, CIMD or DCR client registration, RFC 8414 metadata with `resource` audience binding) fails in the spike, build the AS **in-house** — no further discussion round

The spike ran locally on **21 August 2026** against **Supabase CLI 2.115.0 and GoTrue v2.187.0**.

**Spike result.** Discovery and registration passed; the required custom scope failed:

> | Requirement (D10) | Result |
> |---|---|
> | RFC 8414 metadata | **PASS** — 404 while disabled, 200 once `[auth.oauth_server] enabled = true` |
> | CIMD or DCR registration | **PASS** — a real `POST /auth/v1/oauth/clients/register` returned `201` with a `client_id` |
> | **Custom scopes** | **FAIL** |
> | RFC 8707 `resource` audience | Not proven, and moot once the scope check failed |

**The deciding response.** The request asked for HYVIRAL’s `intel:read` scope (ellipses as in the source):

```text
GET /auth/v1/oauth/authorize?…&scope=intel%3Aread
→ 302 …/callback?error=invalid_request&error_description=unsupported+scope%3A+intel%3Aread
```

## What this shows

A requirement, a versioned experiment, a failing response and a decision tied to a rule written before the test. Evidence changed the provider choice while the product-facing contract stayed stable. The result applies to the versions tested.
