Profiles
fountainApply and fountainRun need an endpoint and a token. Before #2124 that meant FOUNTAIN_ENDPOINT / FOUNTAIN_TOKEN in the shell, which works for one instance and one account but not for a project that targets a self-hosted instance for staging and the hosted one for prod. The fountain.profiles namespace in chant.config.ts names one or more endpoint/token pairs so a project can switch between them with --profile.
Profile shape
Section titled “Profile shape”import type { ChantConfig } from "@intentius/chant/config";// Brings the `fountain` key into ChantConfig.import "@intentius/chant-lexicon-fountain";
export default { lexicons: ["fountain"], fountain: { profiles: { staging: { endpoint: "https://fountain-staging.example.com", token: { env: "FOUNTAIN_STAGING_TOKEN" }, steward: "staging-steward", }, prod: { endpoint: "https://fountain.inevitable.fyi", token: { env: "FOUNTAIN_PROD_TOKEN" }, }, }, defaultProfile: "staging", },} satisfies ChantConfig;Profile fields
Section titled “Profile fields”| Field | Type | Description |
|---|---|---|
endpoint | string | Base URL of the fountain instance this profile targets. |
token | { env: string } | The name of the environment variable that holds the bearer token, never a literal value. FTN001 refuses a literal string here. |
steward | string (optional) | The default steward, the name of a Steward, that chant run --on fountain runs on when the op is listed on no steward of its own. The run resumes that steward’s conversation by channel_id chant:steward:<name>. |
team | string (optional, deprecated) | The old name for steward, from when a steward was a team seat. Read as steward, with a warning. |
An unknown key anywhere in fountain, at the namespace level or inside a profile, fails config load naming the key, the same way forgejo does (chant #1344).
Precedence
Section titled “Precedence”resolveProfile(config, name?) returns:
- The profile named by
name, if one exists. - Otherwise, the profile named by
defaultProfile, if one exists. - Otherwise,
undefined.
fountainApply and fountainRun resolve endpoint and token field by field: an explicit endpoint or token argument always wins over the profile. For whichever field an explicit argument doesn’t cover, they call resolveProfile and, if it returns a profile, read that field from it. Once a profile resolves, it is authoritative: an unset token env var is an error naming the variable, and FOUNTAIN_TOKEN is not read. Only when resolveProfile returns undefined (no fountain.profiles declared, or neither the named nor the default profile exists) do the activities fall back to the pre-#2124 behavior: FOUNTAIN_ENDPOINT / FOUNTAIN_TOKEN, then the hosted default endpoint.
// Explicit args always win, per field.await fountainApply({ manifestPath: "build/fountain.yaml", endpoint: "http://localhost:4000" });
// Resolves through fountain.profiles.staging (or defaultProfile, if "staging" doesn't exist).await fountainApply({ manifestPath: "build/fountain.yaml", profile: "staging" });
// No profile configured at all: falls back to FOUNTAIN_ENDPOINT / FOUNTAIN_TOKEN.await fountainApply({ manifestPath: "build/fountain.yaml" });Selecting a profile from the CLI
Section titled “Selecting a profile from the CLI”# Uses defaultProfilechant run steward-converge --on fountain
# Overrides itchant run steward-converge --on fountain --profile prod--profile (-p) is core’s flag on every chant run subcommand; it reaches a lexicon’s runtime as OpRunStartOptions.profile, and fountain resolves it against fountain.profiles. A name that is not declared there is refused by name rather than falling back to defaultProfile, so a misspelt profile cannot silently run against the wrong instance.
Never a literal token
Section titled “Never a literal token”A profile’s token is always { env: "VAR_NAME" }: an environment variable name, never a secret value.
=== FTN001 refuses a literal string in that position under fountain.profiles, regardless of whether it happens to match a known credential shape:
fountain: { profiles: { // FTN001: literal token under fountain.profiles staging: { endpoint: "https://x", token: "sk-abc123" }, },},