Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,7 @@ jobs:
run: bash scripts/verify-source-files.sh
- name: Build packages
run: pnpm run build
- name: Install Playwright Chromium
run: pnpm --filter @surfaces/interfacectl-cli exec playwright install chromium
- name: Run tests
run: pnpm run test
160 changes: 159 additions & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,164 @@

## Commands

### `init`

First-run onboarding for web surfaces.

**Synopsis:**
```bash
interfacectl init [options]
```

**Description:**
`init` is the primary user-facing entry point for Surfaces onboarding on web surfaces. It:
- analyzes either a local app root (`--app-root`) or a live URL (`--url`)
- classifies the surface as `marketing`, `application`, or `unknown` using platform-owned heuristics
- extracts UI-system attributes across typography, color, layout, motion, icons, shell/auth primitives, sections, and copy-role signals
- decides whether to adopt an existing design system or synthesize a first draft from repeated norms
- writes four artifacts under `contracts/generated/`
- runs `validate-extracted` plus contract validation and prints a short summary

**Options:**

| Option | Description | Default |
|--------|-------------|---------|
| `--url <url>` | Surface URL for remote onboarding | none |
| `--app-root <path>` | Local app root for source-backed onboarding | none |
| `--extract-mode <remote-url\|local-root>` | Source mode override | inferred from inputs |
| `--surface <id>` | Surface identifier override | inferred from URL/path |
| `--surface-name <name>` | Surface display name override | derived from surface id |
| `--surface-kind <marketing\|application\|unknown>` | Confirm low-confidence classification in non-interactive flows | inferred |
| `--auth-profile <name>` | Replay a saved browser-session auth profile for protected remote onboarding | none |
| `--non-interactive` | Disable prompts | `false` |
| `--out-dir <path>` | Output directory for generated artifacts | `contracts/generated` |
| `--analysis-out <path>` | Explicit output path for `<surface>.analysis.json` | derived from `--out-dir` |
| `--draft-out <path>` | Explicit output path for `<surface>.design-system.draft.json` | derived from `--out-dir` |
| `--contract-out <path>` | Explicit output path for `<surface>.contract.json` | derived from `--out-dir` |
| `--report-out <path>` | Explicit output path for `<surface>.extraction.json` | derived from `--out-dir` |

**Artifacts:**

- `contracts/generated/<surface>.analysis.json`
- `contracts/generated/<surface>.design-system.draft.json`
- `contracts/generated/<surface>.contract.json`
- `contracts/generated/<surface>.extraction.json`

**Notes:**
- First-run output is warn-first. Findings are surfaced in the summary rather than blocking the onboarding command unless artifact generation or validation infrastructure fails.
- If surface-kind inference is low confidence, interactive mode asks for confirmation. Non-interactive mode must pass `--surface-kind`.
- For protected remote URLs, `--auth-profile` must point at a replay-ready profile. Interactive `init` can capture one; non-interactive mode fails fast if the profile is missing, expired, legacy, or not replayable.
- First-party or dogfood surfaces are not used as baselines for inference or starter recommendations.

---

### `analyze`

Machine-readable first-run analysis for web surfaces.

**Synopsis:**
```bash
interfacectl analyze [options]
```

**Description:**
`analyze` uses the same first-run analysis engine as `init` but writes only the analysis artifact. It is intended for power users and CI preparation when you want explainable classification and extraction evidence without generating the draft contract/draft-system artifacts.

**Options:**

| Option | Description | Default |
|--------|-------------|---------|
| `--url <url>` | Surface URL for remote analysis | none |
| `--app-root <path>` | Local app root for source-backed analysis | none |
| `--extract-mode <remote-url\|local-root>` | Source mode override | inferred from inputs |
| `--surface <id>` | Surface identifier override | inferred from URL/path |
| `--surface-name <name>` | Surface display name override | derived from surface id |
| `--surface-kind <marketing\|application\|unknown>` | Optional classification confirmation override | inferred |
| `--auth-profile <name>` | Replay a saved browser-session auth profile for protected remote analysis | none |
| `--out <path>` | Output file path for the analysis artifact | `contracts/generated/<surface>.analysis.json` |
| `--out-dir <path>` | Output directory when `--out` is not supplied | `contracts/generated` |

**Output:**
- `contracts/generated/<surface>.analysis.json`

---

### `auth`

Manage replayable browser-session auth profiles for protected remote onboarding.

**Synopsis:**
```bash
interfacectl auth <subcommand> [options]
```

**Subcommands:**

#### `auth capture`

Launches Chromium, opens a clean browser context, waits for manual sign-in, then stores the resulting Playwright `storageState` as a replayable auth profile.

```bash
interfacectl auth capture --profile <name> --url <exact-host-url> [--format text|json]
```

| Option | Description | Default |
|--------|-------------|---------|
| `--profile <name>` | Profile name | required |
| `--url <url>` | URL on the exact host to capture | required |
| `--format <text\|json>` | Output format | `text` |

Notes:
- Profiles are exact-host scoped in v1. If capture ends on a different hostname, the command fails and requires a capture on that host instead.
- Replay state is stored separately from metadata. `interfacectl` uses keychain-first storage with encrypted local-file fallback.
- Generated onboarding artifacts and CLI JSON outputs never include cookies, storage entries, or tokens.

#### `auth list`

Lists locally stored auth profiles and their replay readiness.

```bash
interfacectl auth list [--format text|json]
```

The output includes `status`, `replayReady`, `capturedAt`, `expiresAt`, and storage mode metadata.

#### `auth test`

Validates a local auth profile. Without `--url`, it checks replay readiness only. With `--url`, it performs a real replayed navigation using the same browser observer as remote onboarding.

```bash
interfacectl auth test --profile <name> [--domain <host>] [--url <protected-url>] [--format text|json]
```

| Option | Description | Default |
|--------|-------------|---------|
| `--profile <name>` | Profile name | required |
| `--domain <domain>` | Optional exact-host scope override | inferred from `--url` when present |
| `--url <url>` | Protected URL to validate authenticated replay against | none |
| `--format <text\|json>` | Output format | `text` |

Notes:
- If `--auth-profile` is explicitly supplied to `init` or `analyze`, interfacectl does not silently fall back to anonymous access.
- Legacy v1 profiles remain listable but are not replayable; they must be re-captured.

#### `auth revoke` / `auth clear`

Deletes local auth profile metadata and any stored replay state.

```bash
interfacectl auth revoke --profile <name> --domain <host>
interfacectl auth clear --all
```

If Chromium is not installed locally, install it with:

```bash
pnpm --filter @surfaces/interfacectl-cli exec playwright install chromium
```

---

### `validate`

Validates configured surfaces against a shared interface contract.
Expand Down Expand Up @@ -457,7 +615,7 @@ Fails if the contract’s Phase 0 expectations (`surfaces[].phase0`) conflict wi

**Synopsis:**
```bash
interfacectl validate-extracted --contract <path> --extracted <path> [--surface <id>] [--format text|json] [--exit-codes v1|v2]
interfacectl validate-extracted --contract <path> --extracted <path> [--surface <id>] [--format text|json] [--out <path>] [--exit-codes v1|v2]
```

**Contract shape (policy only; no x_* in policy):**
Expand Down
89 changes: 80 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This repository contains three packages:

- **`@surfaces/interfacectl-cli`** — Command-line interface that consumes the validator to run contract checks from any repository. Most users only need this package.

- **`@surfaces/interfacectl-extractor`** — Library that extracts a contract from a Next.js app (Phase 0). Used by the CLI `generate-contract` command. Exports `extractContractFromNextApp({ appRoot, surfaceId })`.
- **`@surfaces/interfacectl-extractor`** — Library that extracts a contract from a Next.js app (Phase 0). Used by the CLI `init`, `analyze`, and `generate-contract` flows. Exports `extractContractFromNextApp({ appRoot, surfaceId })`.

## Requirements

Expand All @@ -36,17 +36,67 @@ pnpm add -D @surfaces/interfacectl-cli

## Quick Start

After installation, validate your surfaces against a contract:
For a first-time web surface experience, start with `init`:

```bash
interfacectl validate --root . --contract ./contracts/ui.contract.json
interfacectl init --app-root apps/my-app --surface my-app
```

This inspects your surface, classifies it as `marketing`, `application`, or `unknown`, drafts a schema-valid contract, and emits a first design-system draft from repeated UI norms. For detailed command documentation, see [API.md](API.md).

For protected remote apps, capture a replayable browser session first:

```bash
interfacectl auth capture --profile staging-admin --url https://app.example.com/login
interfacectl init --url https://app.example.com --surface customer-app --auth-profile staging-admin
```

For detailed command documentation, see [API.md](API.md).
`interfacectl` replays the saved browser session in Chromium, analyzes the rendered authenticated page, and keeps auth state out of generated artifacts.

## Commands Overview

The CLI provides four main commands:
The CLI provides two first-run commands, browser-session auth helpers, and the validation and enforcement commands:

### `init`

First-run onboarding for web surfaces. `init` analyzes either a local app root or a URL, drafts a first contract, writes a draft design-system artifact, runs validation, and prints a short onboarding summary grouped as adopted, normalized, flagged, and next steps.

```bash
interfacectl init [options]
```

Outputs:

- `contracts/generated/<surface>.analysis.json`
- `contracts/generated/<surface>.design-system.draft.json`
- `contracts/generated/<surface>.contract.json`
- `contracts/generated/<surface>.extraction.json`

Default behavior is warn-first. If surface-kind inference is low confidence, interactive mode asks for confirmation and non-interactive mode requires `--surface-kind marketing|application|unknown`.

### `analyze`

Machine-readable first-run analysis for power users. `analyze` uses the same platform-owned heuristics as `init` but only writes the analysis artifact; it does not mutate contracts outside `contracts/generated/<surface>.analysis.json`.

```bash
interfacectl analyze [options]
```

### `auth`

Browser-session profile management for protected remote onboarding. Use `auth capture` to create or refresh a replayable profile, `auth list` to inspect readiness, `auth test --url ...` to verify real authenticated replay, and `auth revoke` / `auth clear` to remove stored state.

```bash
interfacectl auth capture --profile <name> --url <exact-host-url>
interfacectl auth test --profile <name> --url <protected-url>
interfacectl auth list
```

Notes:

- Profiles are exact-host scoped in v1.
- Remote analysis never silently falls back to anonymous access when `--auth-profile` is explicitly supplied.
- If Chromium is missing locally, install it with `pnpm --filter @surfaces/interfacectl-cli exec playwright install chromium`.

### `validate`

Expand Down Expand Up @@ -82,9 +132,9 @@ This command does **not** perform enforcement or runtime gating. It produces a s
interfacectl compile --contract <path> --out <dir>
```

### `generate-contract` (Phase 0)
### `generate-contract` (Phase 0 expert command)

Extracts a **deterministic contract artifact** from a Next.js app by analyzing app code and config. This is **contract extraction only** — no enforcement, no network calls.
Extracts a **deterministic contract artifact** from a Next.js app by analyzing app code and config. This is **contract extraction only** — no first-run classification, no design-system draft, and no onboarding summary. Prefer `interfacectl init` for the user-facing entry point.

**Phase 0 scope:** Routes (app router), layout shell presence (`app/layout.tsx` or `app/(shell)/layout.tsx`), design system usage (`@surfaces/ui` component imports), and auth posture (`/auth` routes). The command also seeds `color.allowedValues` and web-surface `icons.allowedSources` from observed descriptors (default `icons.policy: "warn"`). Values that cannot be extracted safely are omitted and reported as warnings in the extraction report.

Expand All @@ -101,9 +151,9 @@ interfacectl generate-contract --app-root <path> --surface <surfaceId> [--out <p

Running the command twice produces identical contract and report (stable key order, no timestamps). See [API.md](API.md) for full options.

### `validate-extracted` (Phase 0.5)
### `validate-extracted` (Phase 0.5 expert command)

Validates that the **declared policy** (contract `surfaces[].phase0`) matches **extracted reality** (from the extraction report or generated contract). Use after `generate-contract` in CI to fail when auth posture, shell, auth routes, or design-system expectations disagree with what was extracted.
Validates that the **declared policy** (contract `surfaces[].phase0`) matches **extracted reality** (from the extraction report or generated contract). `init` already runs this during onboarding; use the command directly in CI or for focused debugging.

```bash
interfacectl validate-extracted --contract <path> --extracted <path> [--surface <id>] [--format text|json] [--exit-codes v2]
Expand Down Expand Up @@ -176,6 +226,27 @@ Runtime (not implemented here)

## Usage Examples

### First run

Analyze and draft a first contract from a local web app:

```bash
interfacectl init --app-root apps/my-app --surface my-app
```

Inspect a public URL without writing a contract:

```bash
interfacectl analyze --url https://example.com --surface example-site
```

Capture a protected app session and analyze the authenticated surface:

```bash
interfacectl auth capture --profile customer-admin --url https://app.example.com/login
interfacectl analyze --url https://app.example.com/dashboard --surface customer-app --auth-profile customer-admin
```

### Validation

Validate all surfaces against a contract:
Expand Down
16 changes: 16 additions & 0 deletions packages/interfacectl-cli/dist/commands/analyze.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { type AnalysisSourceMode, type WebSurfaceKind } from "../utils/first-run-analysis.js";
type ExtractMode = AnalysisSourceMode;
export interface AnalyzeCommandOptions {
url?: string;
appRoot?: string;
extractMode?: ExtractMode;
surface?: string;
surfaceName?: string;
surfaceKind?: WebSurfaceKind;
authProfile?: string;
out?: string;
outDir?: string;
}
export declare function runAnalyzeCommand(options: AnalyzeCommandOptions): Promise<number>;
export {};
//# sourceMappingURL=analyze.d.ts.map
1 change: 1 addition & 0 deletions packages/interfacectl-cli/dist/commands/analyze.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading