# Aztris ME Website Integration

Contract: `aztris-me-property-integration/1`

Aztris ME is the authentication authority. The site owner creates the property in Aztris ME Utility and downloads its integration ZIP. That ZIP contains the property-specific `AME.php`.

If `AME.php` is not present, stop and ask the site owner for that generated file. Do not reconstruct it and **do not modify it**.

## What the website stores

The durable identity bridge is the ME remote identifier returned by `ame_remote_id()` (`ame_subject()` is the compatibility alias).

```text
local_user_id    ame_remote_id
42               xmesccioy_A83k...
91               xmesccioy_H7mx...
```

Store that value beside the website's local user record, or in a separate mapping table. Never use email, name, handle, or another mutable claim as the linkage key.

The remote identifier identifies the returning ME account to this website. It does not grant local authorization by itself. The website remains authoritative for its own users, roles, permissions and sessions.

## Required procedure

1. Place the generated `AME.php` in the website root. Do not edit it.
2. Inspect the existing website authentication/session boundary before changing it.
3. Start ME login with `ame_authorize_url($localReturnPath)`.
4. On a successful connection, use `ame_remote_id()` as the stable foreign identity key for this website.
5. Map that remote identifier to exactly one local user where the website has local users.
6. Create or resume the website's normal local browser session using its existing mechanisms.
7. Use `ame_is_connected()` / `ame_connection()` as the AME connection authority.
8. Use `ame_claim($name)` only for information this property was allowed to receive.
9. Call `ame_revalidate_now()` before a local action that requires a fresh central check.
10. Fail closed: unavailable or invalid ME validation must never grant access.

## Controls

```php
ame_authorize_url('/account/');
ame_permission_url('profile.name', '/profile/');
ame_is_connected();
ame_connection();
ame_remote_id();
ame_subject();
ame_classification();
ame_claim('profile.name');
ame_revalidate_now();
ame_disconnect_local();
```

## Front-end examples

Plain link:

```php
<a href='<?= htmlspecialchars(ame_authorize_url('/account/'), ENT_QUOTES, 'UTF-8') ?>'>Login with Aztris ME</a>
```

Button form without JavaScript:

```php
<form method='get' action='/AME.php'>
    <input type='hidden' name='ame' value='authorize'>
    <input type='hidden' name='return' value='/account/'>
    <button type='submit'>Login with Aztris ME</button>
</form>
```

Server-side gate:

```php
require __DIR__ . '/AME.php';
if (!ame_is_connected()) {
    header('Location: ' . ame_authorize_url($_SERVER['REQUEST_URI'] ?? '/'));
    exit;
}
$ameRemoteId = ame_remote_id();
```

Existing user table:

```text
users.id    users.ame_remote_id
42          xmesccioy_A83k...
```

## Security invariants

- Never expose the property secret in HTML, JavaScript, URLs or browser storage.
- Never copy or attempt to read the ME cookie from the website.
- Never trust a remote identifier, role, claim or classification supplied by the browser.
- Never accept arbitrary remote callbacks or external return URLs.
- Never grant a local administrator role merely because an ME account is connected.
- Never weaken HTTPS or the client fail-closed behavior.
- Do not replace this native contract with OAuth, OIDC, SAML or a custom browser token flow.

## Privacy model

Each Property gets a different ME remote identifier for the same account. That lets a website recognize the returning ME account without learning the account's global ME ID. Name, email, handle, and other profile information are separate claims and are shared only when the Property is allowed to receive them.

## Acceptance checks

- An anonymous browser cannot access the protected content.
- Login performs a top-level visit to Aztris ME.
- Successful approval returns to the intended local path.
- Refresh does not require another login while the local connection is valid.
- Direct callback invocation cannot establish a login.
- Revocation or failed revalidation removes access according to the website's policy.
- The property secret never appears in browser-visible output.
- Failure to contact or validate ME never grants access.
