# Add consumer organization selection to a website

Use the verified Token/PHP 0.1.4 package behind the website to call
`M7IdentitySDK::managedOrganizations(token, options)`. It includes the
Organizations and Emails classes. Follow the
[package installation and root layout](https://m7.org/docs/sdk/m7-identity/cli/organization-access.md#installation-and-release-boundary)
alongside the [website installation](https://m7.org/docs/sdk/m7-identity/website/installation.md).

The requesting app must also be allowed by each org owner's discovery policy.
Only stored owners edit **Access → Policy**. Ordered app/org ACL rules use the
first match; a deny cannot be bypassed by membership role. With no match, an
app owned by that org uses `same_org_discoverable`, and other apps use
`discoverable`; both default off. App identity and ownership come from the
validated token's `client_id`. App ownership, the caller's Management membership,
owner permission to disclose, and website resource authorization are separate
checks. An empty success can reflect policy filtering; a failed lookup is an error.
Local imported identities cannot bypass this policy. See the
[full disclosure contract](https://m7.org/docs/sdk/m7-identity/cli/organization-access.md#owner-controlled-organization-disclosure).

1. Register `orgs` for the consumer OAuth client, explicitly request it in
   hosted authorization and obtain consent. Keep PKCE/state/nonce and the
   registered client/sender-binding policy. Device authorization rejects `orgs`.
2. Use the active login token and verified consumer subject/client ID. The org
   helper does not own a browser session, acquire/refresh a bundle, generate
   proofs or persist org results. An `orgs`-only token can call the org endpoint;
   standard UserInfo still requires `openid`.
3. Resolve the trusted endpoint before producing a fresh DPoP proof, then fix
   that endpoint in the request. A proof for UserInfo or the website API cannot
   authorize this different resource. For mTLS use the discovered top-level
   `m7_mtls_orgs_endpoint` and bound certificate.
4. Accept only a successful report and exact subject binding. Render org names,
   scopes, tag data and public JSON as literal text. Empty org lists are valid;
   failed reports are errors and carry no accepted orgs/subject. Preserve nonce
   challenges for explicit fresh-proof recovery.
5. Apply your website's resource policy to the live facts. Seeing an org or a
   role/tag is not a grant to its buckets/blogs. Original identity-only results
   remain compatible but grant no absent authorization facts.

```php
use M7\Identity\M7IdentitySDK;

$sdk = new M7IdentitySDK();
$options = ['client_id' => $verifiedClientId, 'expected_sub' => $verifiedSubject];
$endpoint = $sdk->managedOrganizationsEndpoint($options);
$options['endpoint'] = $endpoint;
// For a bound token, add a caller-created POST proof for $endpoint and $token.
$report = $sdk->managedOrganizations($token, $options);
if (!$report->ok()) {
    throw new RuntimeException($report->reason() ?? 'Organization lookup failed');
}
```

Current results carry caller `access_level` and one implicit Management
group/membership, role, membership `pub`, and assigned tags with definition
`data`, plus per-org `consumer` and `tenant` app lists (`id`, `client_id`,
`name`). The lists contain the org's live owned registrations and show related
apps; they do not grant access between apps. These are three distinct data locations when compared with org
`organization.data`. Only public membership data is exported; no `pri`, other
principals or expiry fields. PHP associative decoding makes empty objects `[]`.
`$report->client()` separately identifies the token's app. A personal consumer
app has `org: null` and tenant `{id: "00000000-0000-0000-0000-000000000000",
slug: "m7-identity-consumer"}`; a policy-hidden org-owned app has `client: null`.
See the [complete validation/report/options contract](https://m7.org/docs/sdk/m7-identity/cli/organization-access.md)
and [SSO normative org profile](https://m7.org/docs/api/sso.user.m7.org/provider-profile.md#consumer-organization-discovery).
Registered signed/encrypted response policy must pass verification before facts
are trusted. Optional certificate/validation caches remain separate from org
result persistence, which this operation does not supply.

Backend workers can also use an ordinary client-credentials token with
explicitly requested registered `orgs`. Bind `expected_sub` to the verified
public `client_id` and assign that app its own Management membership; creator
access and registration ownership do not substitute for membership. Personal
owner proxies and tenant member tokens cannot use this endpoint.

API BigFS already uses the platform remote service to transport these facts;
its local import boundary stores org identity only. See
[BigFS acquisition](https://m7.org/docs/api/api.bigfs.m7.org/organizations.md)
and [upgrade order](https://m7.org/docs/api/api.user.m7.org/organization-upgrade.md).
Consumer-service permission adoption is separate; Blog adoption remains future
work. For the distinct API User email list use [account emails](https://m7.org/docs/sdk/m7-identity/website/account-emails.md).
