← Files CrowdStrike Falcon FoundryARCHIVED FILE
skills/development-workflow/references/advanced-patterns.md
15.6 KB · Oct 9, 2026 · 00:07 UTC
# Advanced Patterns
## Lifecycle Phases
### Phase 0: CLI Prerequisite Check
Before any Foundry work, verify the CLI is installed and authenticated:
```bash
# 1. Check CLI is installed (cross-platform — fails if not installed)
foundry version
# If not installed:
# macOS/Linux: brew tap crowdstrike/foundry-cli && brew install crowdstrike/foundry-cli/foundry
# Windows: Download https://assets.foundry.crowdstrike.com/cli/latest/foundry_Windows_x86_64.zip
# Expand the archive and add the installation directory to PATH
# 2. Check authentication
foundry profile active
# If no profile exists, guide through one of:
# foundry profile create --name "my-profile" --api-client-id "<id>" --api-client-secret "<secret>" --cid "<cid>" --cloud-region "us-1" --no-prompt
# foundry login (interactive — opens browser)
```
### Phase 1: Discovery
- Profile setup and environment validation
- Requirements gathering and capability mapping
- Template selection based on app type
### Phase 2: Scaffolding (CLI-First)
**CRITICAL: Use CLI scaffolding commands first, even when using superpowers planning skills.** If an external planning skill (e.g., `superpowers:writing-plans` or `superpowers:subagent-driven-development`) generates a plan, the plan's tasks MUST use CLI commands for scaffolding. Do not manually create manifest.yml, workflow YAML shells, or UI boilerplate that the CLI can generate.
Use CLI scaffolding commands to generate artifacts. The CLI creates directories, copies files, and updates manifest.yml with generated IDs. **Write spec/schema files to `/tmp/` first** — the CLI copies them into the project. Hand-write only what the CLI cannot generate (workflow YAML content, OpenAPI spec JSON, UI component code, collection schema JSON, Foundry-specific OpenAPI annotations like `x-cs-operation-config`).
> **Note:** OAuth scopes are auto-managed by the platform for CLI-created artifacts. Do NOT manually add scopes like `api-integrations:read` to `manifest.yml` — Foundry handles permissions for its own artifacts automatically. Only use `foundry auth scopes add` for additional Falcon Platform API scopes (e.g., `devices:read`, `detects:read`) not covered by the scaffolded capabilities.
### Phase 3: Development
- **MANDATORY sub-skill delegation** for all capability development
- `foundry ui run` state management across development sessions
- Continuous manifest.yml coordination and validation
### Phase 4: Integration
- Manifest validation and testing
- End-to-end testing patterns
- `foundry apps deploy` for cloud testing
### Phase 5: Release
- Cloud environment testing
- `foundry apps release` to catalog
- Documentation and handoff
## Manifest Coordination Patterns
**Manifest-First Development (MANDATORY):**
1. Define all capabilities in manifest.yml BEFORE implementation
2. Specify permissions, routes, and dependencies upfront
3. Validate manifest before starting capability development
4. Update manifest immediately when adding capabilities
**Schema-Driven Coordination:**
- Collections define data contracts for all capabilities
- Functions reference collection schemas in TypeScript/Go types
- UI components use generated types from schemas
- Workflows access collections through validated operations
**Permission Coordination:**
- UI extensions declare required Falcon API scopes
- Functions request minimal necessary permissions
- Workflows inherit permissions from component capabilities
- RTR scripts specify endpoint access requirements
**Dependency Resolution:**
- Collections MUST exist before functions that use them
- Functions MUST exist before workflows that call them
- UI MUST exist before workflows that display results
- API integrations MUST exist before capabilities that consume them
**Continuous Validation:**
- Use `npx @redocly/cli lint` to validate OpenAPI specs — do NOT use Python, Ruby, or other language-specific YAML parsers
- Use `foundry apps validate --no-prompt` to validate the manifest and schemas without deploying
- Use `foundry apps run` to validate the manifest on startup
- Restart `foundry ui run` when permissions change
- Test capability integration with minimal viable examples
## CLI State Management
**Current Working Directory:** Always maintain awareness of current project context
- `pwd` before any foundry command
- Navigate to correct app directory: `cd path/to/foundry-app`
- Verify manifest.yml exists: `ls manifest.yml`
**Foundry Profile State:** CLI authentication and environment
- Check current profile: `foundry profile list`
- Check active profile: `foundry profile active`
- Switch if needed: `foundry profile activate --name <profile-name>`
**Development Server State:** UI serving for local development
- Run `foundry ui run` during UI development — **deploy first if the UI calls API integrations, collections, or functions** (those resolve from the cloud)
- Use `foundry apps run` to start the full app locally in dev mode (validates manifest on startup)
- Monitor for permission errors indicating manifest drift
- Restart server after manifest.yml changes
**Build State:** Asset compilation and deployment readiness
- Track dependency changes: monitor `package.json` / `go.mod` modifications
- Rebuild on schema changes: collections affect TypeScript types
## App Lifecycle Operations
### Import, Export, Clone, and Sync
| Operation | Tool | Notes |
|-----------|------|-------|
| **Import** | Falcon console only (not CLI) | Accepts tar.gz or ZIP |
| **Export** | Falcon console only (not CLI) | Exports full app package |
| **Clone** | CLI only: `foundry apps clone` | Creates a local copy of a deployed app |
| **Sync** | CLI: `foundry apps sync` | Pulls a deployed version's files (including the IDs the deploy assigned) into a **new subdirectory named after the app**, not the current directory |
```bash
# Clone an existing deployed app to local
foundry apps clone --name "existing-app"
# Sync a deployed version's files (and the IDs the deploy assigned) into the CURRENT directory.
# -d . targets the current dir instead of a new subdirectory; --replace-all overwrites existing files.
# Under --no-prompt, --deployment-version is required, else: "flag --deployment-version is required
# when --no-prompt flag is used". --app-id selects the app when the manifest's app_id is blank.
foundry apps sync --deployment-version v0.1.0-pre-release -d . --replace-all --no-prompt
```
**`sync`'s target directory defaults to the app name.** Without `-d/--directory` it writes into a new `AppName/` directory (spaces included), which looks like it ignored your project — pass `-d .` (with `--replace-all` when the directory already has files) to sync in place. *(Confirm the exact flags with `foundry apps sync --help`; CLI flags can change between releases.)*
**The ID-stripping convention fights local tooling.** If you commit `manifest.yml` with blanked IDs (the `foundry-sample-*` pattern, so the app installs into any CID), local commands still need the real IDs present. `foundry functions exec` fails with `app_id not found in manifest; deploy the app first`, and `foundry apps deploy` needs them to target the existing app instead of creating a new one. Re-fill the IDs from the deployed app before working locally, then blank them again before committing.
Don't sync into the working copy to do it: `-d . --replace-all` replaces **every** file with the deployed version, so any function, UI, or manifest edit that isn't deployed yet is lost. Sync into a scratch directory and copy only the IDs across. Copying the whole synced `manifest.yml` has the same problem for undeployed manifest edits (a changed `model`, a new `ignored` pattern), and the synced file is re-indented besides. The `yq` merge below matches pages by key and functions and agents by name; extend it for other artifact types your app has (extensions, workflows, API integrations):
```bash
foundry apps sync --app-id <app-id> --deployment-version <version> -d /tmp/app-deployed --replace-all --no-prompt
S=/tmp/app-deployed/manifest.yml
yq -i "
.app_id = load(\"$S\").app_id |
.ui.pages |= with_entries(.key as \$k | .value.id = load(\"$S\").ui.pages[\$k].id) |
.ui.navigation.id = load(\"$S\").ui.navigation.id |
.functions[] |= (.name as \$n | .id = (load(\"$S\").functions[] | select(.name == \$n) | .id)) |
.docs.id = load(\"$S\").docs.id |
.ai.agents[] |= (.name as \$n | .id = (load(\"$S\").ai.agents[] | select(.name == \$n) | .id))
" manifest.yml
git diff manifest.yml # only id lines should change
```
### Development Mode vs Preview Mode
| Feature | Development Mode | Preview Mode |
|---------|-----------------|--------------|
| Activation | `foundry ui run` | Enable in console after deploy |
| Port | 25678 | N/A (uses deployed assets) |
| Source | Polls localhost | Uses deployed build |
| Purpose | Active UI development | Testing deployed UI |
| Hot reload | Yes | No |
> **Mutually exclusive:** Only one mode can be active at a time. Disable development mode before enabling preview mode, and vice versa.
### What the Deploy Packages (`ignored:`)
`foundry apps deploy` walks the app directory and packages every file except:
- **Hidden paths.** Any path with a component starting with `.` is skipped, so `.venv`, `.pytest_cache`, `.env`, and `.git` never need `ignored:` entries.
- **SVG files.** `*.svg` is always excluded (an XSS guard), which is why a page should inline an SVG rather than reference one by path.
- **Anything matching an `ignored:` entry.**
Each `ignored:` entry is a **Go regular expression**, not a glob, matched unanchored against the path relative to the app root. A glob like `**/*.test.ts` is an invalid regex and fails `foundry apps validate` with `ignored item "..." is not a valid regular expression`. Because matching is unanchored, `tests` also matches `contests.py`; anchor on path separators:
```yaml
ignored:
- (^|/)__pycache__(/|$)
- ^functions/[^/]+/tests(/|$)
- (^|/)node_modules(/|$)
- \.test\.ts$
```
`__pycache__/` and `tests/` are the entries a Python function usually needs; without them, the deploy lists the `.pyc` files and test modules.
**Ignoring `tests/` makes `exec` warn on every run.** `foundry functions exec` compares the whole local function directory against the last deployment, and the deployment has no `tests/`, so it reports undeployed local changes even right after a successful deploy. Pass `--ignore-deploy-warning` once you have confirmed the handler itself is deployed (see `functions-development/references/execution-and-testing.md`).
### App Logo
The manifest `logo:` field is a relative path to a small square PNG, ~160x160, matching the `foundry-sample-*` apps (e.g. `logo: images/logo.png`). Two things about it are easy to get wrong:
- **It is only picked up on the app's first deploy.** The App Catalog icon is set from `logo:` when the app is first created on a cloud. Adding or changing the logo in a later patch deploy does not update the catalog icon; it keeps the generated text avatar (the app's initials). To change an existing app's icon you effectively need a fresh app (delete and redeploy), so get the logo right before the first deploy.
- **A logo-only change will not deploy.** `foundry apps deploy` versions artifacts (functions, collections, UI pages, agents). If the diff from the last version contains only the logo image and/or manifest metadata with no artifact change, deploy fails with `no deployable artifacts found`. There is no `--force`. Bundle the logo with an artifact change, or include it in the first deploy.
If a UI page displays the same logo, inline the SVG in the page markup rather than referencing the PNG by path. The page runs in a sandboxed iframe without `allow-same-origin` and cannot load an image file from outside its own `src/` directory.
**Deleting an app:** `foundry apps delete --force-delete --no-prompt` removes the app from the cloud but keeps the local files. The `--local-files` flag *also* deletes the local manifest and app directory, so omit it unless you intend to erase the local project too.
## Session Handoff
When transferring Foundry development between sessions, preserve:
- Current foundry profile and authentication status
- Development server state (`foundry ui run` status and port)
- Current working directory and manifest.yml validation state
- Last deployment status and environment
- Capability development progress per sub-skill
- OAuth scope conflicts and resolution decisions
## Implementation Planning
Before implementing Foundry capabilities, plan the following:
1. **Manifest dependency ordering**: Collections before functions that use them, functions before workflows that call them, UI after backend capabilities are ready
2. **OAuth scope inventory**: List all required scopes across capabilities; request minimal permissions
3. **Capability mapping**: Map each requirement to the correct sub-skill (UI, Collections, Functions, Workflows, API Integration)
4. **CLI state requirements**: Identify which profiles, environments, and development servers are needed
### Execution Checkpoints
Between capability phases, verify:
- `foundry ui run` reflects latest manifest changes (restart if permissions changed)
- Tests pass for completed capabilities before starting dependent ones
## OpenAPI Spec Sourcing
**NEVER write OpenAPI specs from scratch.** When users need API integrations, ask first if they have an existing spec or know where to download one. Search locally, download from the vendor's GitHub/docs, or trim a large spec to the needed operations. The api-integrations sub-skill handles all spec preparation including Foundry-specific server variable fixes and `x-cs-operation-config` annotations.
## Workflow YAML Action ID Patterns
For action IDs in workflow YAML, use the `api_integrations.{name}.{operationId}` pattern for API integration operations. Do NOT guess platform action docIDs (e.g., `send_email`, `log`). If the workflow needs platform actions, set `provision_on_install: false` and add a TODO comment -- the user will configure these in the Falcon console's App Builder.
## Deployment Nuance
`foundry apps deploy` requires `--change-type` and `--change-log`. The `--no-prompt` flag is available as a global Controller flag and skips the deployment confirmation prompt and TUI monitor, but is not required when all flags are provided. `foundry apps release` requires `--deployment-id`, `--change-type`, and `--notes` and works fully non-interactively when all three flags are provided.
## Testing an Existing App Locally
When running e2e tests against a CrowdStrike/foundry-sample-* app on GitHub:
1. **Configure credentials** — copy `.env.sample` to `.env` in the `e2e/` directory and fill in valid Falcon credentials (username, password, TOTP secret, base URL) and app name. `APP_NAME` defaults to the repo name. `FALCON_` credentials must be for a non-SSO user because TOTP is used in e2e tests. This file is gitignored and required for local test runs.
2. **Align the app name** — the manifest `name` and the e2e test `APP_NAME` environment variable (in `.env`) must match for local test runs. CI pipelines typically rewrite the manifest name automatically (e.g., `${REPO}-ci-${PIPELINE_ID}`), so this only affects local development. Preferred approach: update the manifest `name` to match the repo name (e.g., `foundry-sample-logscale`) to avoid spaces and simplify artifact lookup. Remember to `git checkout manifest.yml` after deploy to revert ID changes.
3. **Deploy and release:**
```bash
foundry apps deploy --change-type Patch --change-log "e2e testing" --no-prompt
# Poll until successful
foundry apps list-deployments
# Release
foundry apps release --deployment-id <id> --change-type Patch --notes "e2e testing" --no-prompt
```
4. **Run tests:** `cd e2e && npm test`
5. **Revert manifest:** `git checkout manifest.yml` (deploy writes IDs into the manifest)
SHA-256: c92b33b3c5d7e0d763cfc6ffcf7085731e0d1f82251777a72d3b20202b3e6f4a