> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.ekanos.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Publishing & Target Verification

> Safe publish workflows with seat verification to prevent publishing to wrong sources.

The Ekanos CLI enforces **seat-based verification** so you cannot publish to the wrong Ekanos source by accident. A logged-in developer often holds seats on more than one source, and a typo or stale config must never silently publish to the wrong one.

## The safety mechanism

Three commands work together:

```bash theme={null}
# 1. See what you can publish to
ekanos sources

# 2. Point this project at a specific source
ekanos use acme-crm

# 3. Publish — verified before anything is packed or sent
ekanos publish
```

`ekanos sources` answers "which sources do I hold a seat on?" From there, `ekanos use` pins a target and `ekanos publish` verifies it before uploading anything.

## Sources and seats

`ekanos sources` lists every source on which you hold a `developer` or `source_admin` seat:

```
$ ekanos sources
sources:
  * acme-crm  Acme CRM  [developer]
    acme-billing  Acme Billing  [source_admin]
(* marks the current project publish target)
```

The `*` marks the `source` saved in this project's `ekanos.json`. If that slug is not in your list, the output says so. In JSON mode, `data` is `{ host, sources: [{ id, slug, name, roles }], activeSource }`.

## Publish target resolution

`ekanos publish` resolves its target from:

1. **`--source` flag** (explicit)
2. **`source` field in `ekanos.json`** (implicit)

With neither, it fails with `validation` (exit 3): `No Ekanos source given for the submission.` The hint lists your seats when they can be fetched.

## Safety rules

Before packing or submitting anything, `publish` fetches your seat list and applies these rules:

| Source came from | Your seats | Terminal mode | Behavior |
| - | - | - | - |
| any | not among your seats | any | **Forbidden** (exit 5) with your seat list in the hint |
| `--source` flag | any | any | **Proceeds** — an explicit flag is consent |
| `ekanos.json` | exactly 1 | any | **Proceeds**, printing the target |
| `ekanos.json` | more than 1 | human mode and a real terminal on stdin | **Prompts** `Proceed? [y/N]`; `--yes` skips it |
| `ekanos.json` | more than 1 | JSON mode, piped, or non-interactive stdin | **Never prompts** — proceeds only with `--yes`; otherwise `validation` (exit 3) |

### Plain English

* **One seat?** Just publish. Nothing to disambiguate.
* **Explicit `--source`?** Just publish. You said which one.
* **Several seats, source from `ekanos.json`, human at a terminal?** The CLI prints the target and asks `Proceed? [y/N]`.
* **Several seats, source from `ekanos.json`, script/agent/pipe?** Pass `--source`, or `--yes` to confirm the target already in `ekanos.json`.
* **Not a seat you hold?** Always forbidden, with a hint listing your actual seats.

## Workflow examples

### One source

After the first publish, `ekanos.json` remembers the source:

```bash theme={null}
# First time
ekanos publish --source acme-crm

# ekanos.json now has "source": "acme-crm"

# Later, no flags needed
ekanos publish
```

### Several sources

Use `ekanos use` to switch targets:

```bash theme={null}
ekanos sources
ekanos use acme-crm-prod
ekanos publish

ekanos use acme-crm-staging
ekanos publish
```

### Agent publishing

Never pass `--yes` through an ambiguity you haven't resolved:

```bash theme={null}
# Right: be explicit
ekanos publish --source my-source

# Right: check, then choose deliberately
ekanos sources
ekanos publish --source my-source

# Wrong: silencing the check
ekanos publish --yes
```

### CI/CD pipeline

Commit `ekanos.json` with the intended `source`, then either pass `--source` explicitly or confirm the committed target with `--yes`:

```bash theme={null}
ekanos use my-ci-target
git add ekanos.json
git commit -m "Set publish target to my-ci-target"

# In CI
ekanos publish --yes
```

`--yes` exists for a human's already-confirmed intent and for CI pipelines pinned to one source — not as a way to silence the check.

***

## Complete publish flow

1. **Preflight**
   * Resolve the host and require a stored session (exit 4 without one)
   * Load `ekanos.json` and run the schema-skew gate (exit 9)
   * Refuse if the host has declared this CLI version unsupported (exit 9)
   * Resolve the source (exit 3 without one)

2. **Validate**
   * Run the same findings pass as `ekanos validate`
   * Escalate `project.host-compiler-rules` from `warn` to `error`
   * Refuse on any error-severity finding with `gate_failed` (exit 10) and the findings in `data.findings` — nothing is uploaded

3. **Verify the target**
   * Fetch your seat list and apply the safety rules above

4. **Pack**
   * Build a gzipped tarball of `ekanos.json`, `package.json`, `README.md` (if present), root `tsconfig*.json` and vitest config, and everything under `src/`
   * Dotfiles, `node_modules`, and symlinks are excluded
   * Archives over 4 MiB fail with `validation` (exit 3)

5. **Submit**
   * POST to `/api/partner/submissions` at the `package.json` version

6. **Report**
   * `data.source` is `{ id, slug, name }` — exactly which source received the submission — alongside `submissionId`, `state`, and `archiveSha256`
   * `source` (and `host`, if absent) are saved to `ekanos.json`

***

## Error handling

### Forbidden (exit 5)

```
Error: This account does not hold a seat on source "wrong-source" on https://your-ekanos-host.
Hint: You hold a seat on: acme-crm (developer), acme-billing (source_admin). Pass "--source <slug>" naming one of these, or run "ekanos use <slug>" to set the project's default.
```

**Fix:** Use a source from the list: `ekanos use <source>` or `ekanos publish --source <source>`.

### Ambiguous target (exit 3)

```
Error: Ambiguous publish target: this account holds 2 developer seats and the source was resolved from ekanos.json, not an explicit flag.
Hint: You hold seats on: acme-crm (developer), acme-billing (source_admin). Pass "--source <slug>" to name the target explicitly, add "--yes" to confirm the target already in ekanos.json non-interactively, or run "ekanos use <slug>" to change the project's default.
```

Pick one:

1. **Pass `--source`** explicitly this run
2. **Run `ekanos use`** to change the project's default
3. **Pass `--yes`** only if `ekanos.json` already names the target you intend

### Refused on findings (exit 10)

In human mode, the CLI prints `Refusing to publish: 2 findings.`, then the findings, then `ekanos publish failed: 2 errors`. In JSON mode, `error.message` is `Refusing to publish: 2 validation findings.` and the findings are in `data.findings`. Nothing was uploaded.

**Fix:** Run `ekanos validate`, fix the error-severity findings, and publish again.

### Version already submitted (exit 7)

```
Error: Version 0.1.0 of "acme-crm" is already submitted.
Hint: Submitted versions are immutable. Bump the "version" field in package.json and publish again.
```

The host may return its own message in place of this one; the exit code and hint are the same.

***

## Post-submit monitoring

Use `ekanos status` to track your submission:

```bash theme={null}
# Show this project's submissions and their states
ekanos status

# Block until the current version reaches a verdict
ekanos status --watch
```

A version moves from `submitted` (awaiting the gate) to `gated` (passed the gate, awaiting admission) or `rejected`, then `dev`. `status --watch` polls every 30 seconds and exits `0` on `gated` or `dev`, or `10` on `rejected` with the gate's findings in `data.findings`. `ekanos status --findings` renders each version's full finding list.

See [Commands: status](/cli/commands#status) for full details.

***

## Troubleshooting

### No source configured

`publish` found no `--source` and no `source` in `ekanos.json`. Either:

* Run `ekanos use <source>` to pick one
* Pass `--source <source>` to this publish

### Source not in your seat list

A typo in the slug, or you don't hold a seat on it. Run `ekanos sources` to check the slug; if you need a seat, ask your Ekanos operator.

### Republishing the same version

Submitted versions are immutable: republishing the same `package.json` version exits 7. Bump `version` in `package.json` (and in `defineIntegration()`, which `validate` checks against it) and publish again.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.