Skip to content
Closed
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
24 changes: 20 additions & 4 deletions .github/workflows/security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,19 @@ jobs:
} >> "${GITHUB_STEP_SUMMARY}"
exit 1

fleet_self_service_tests:
name: Fleet Self-Service Tests
runs-on: macos-15
steps:
- name: Check Out Repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6

- name: Run Native Fleet Regression Tests
# Extracts helpers only; HTTP is mocked and no installations are requested.
run: |
/bin/zsh --no-rcs tests/fleet-self-service.zsh
/bin/zsh --no-rcs tests/fleet-transport.zsh

zsh_syntax:
name: Zsh Syntax
runs-on: ubuntu-latest
Expand Down Expand Up @@ -445,6 +458,7 @@ jobs:
- semgrep
- gitleaks
- zsh_syntax
- fleet_self_service_tests
- shellcheck
steps:
- name: Security Scan Complete
Expand All @@ -454,6 +468,7 @@ jobs:
semgrep_result="${{ needs.semgrep.result }}"
gitleaks_result="${{ needs.gitleaks.result }}"
zsh_syntax_result="${{ needs.zsh_syntax.result }}"
fleet_tests_result="${{ needs.fleet_self_service_tests.result }}"
shellcheck_result="${{ needs.shellcheck.result }}"

badge() {
Expand All @@ -468,22 +483,23 @@ jobs:
semgrep_badge="$(badge "${semgrep_result}")"
gitleaks_badge="$(badge "${gitleaks_result}")"
zsh_syntax_badge="$(badge "${zsh_syntax_result}")"
fleet_tests_badge="$(badge "${fleet_tests_result}")"
shellcheck_badge="$(badge "${shellcheck_result}")"

{
echo "## Security Scan Summary"
echo
echo "Semgrep ${semgrep_badge} | Gitleaks ${gitleaks_badge} | Zsh Syntax ${zsh_syntax_badge} | ShellCheck ${shellcheck_badge}"
echo "Semgrep ${semgrep_badge} | Gitleaks ${gitleaks_badge} | Zsh Syntax ${zsh_syntax_badge} | Fleet Tests ${fleet_tests_badge} | ShellCheck ${shellcheck_badge}"
echo
if [[ "${semgrep_result}" == "success" && "${gitleaks_result}" == "success" && "${zsh_syntax_result}" == "success" && "${shellcheck_result}" == "success" ]]; then
if [[ "${semgrep_result}" == "success" && "${gitleaks_result}" == "success" && "${zsh_syntax_result}" == "success" && "${fleet_tests_result}" == "success" && "${shellcheck_result}" == "success" ]]; then
echo "🐉 Mac Admin Security Dragon Slain"
else
echo "⚠️ Security Scan requires attention"
fi
} >> "${GITHUB_STEP_SUMMARY}"

echo "Semgrep ${semgrep_badge} | Gitleaks ${gitleaks_badge} | Zsh Syntax ${zsh_syntax_badge} | ShellCheck ${shellcheck_badge}"
if [[ "${semgrep_result}" == "success" && "${gitleaks_result}" == "success" && "${zsh_syntax_result}" == "success" && "${shellcheck_result}" == "success" ]]; then
echo "Semgrep ${semgrep_badge} | Gitleaks ${gitleaks_badge} | Zsh Syntax ${zsh_syntax_badge} | Fleet Tests ${fleet_tests_badge} | ShellCheck ${shellcheck_badge}"
if [[ "${semgrep_result}" == "success" && "${gitleaks_result}" == "success" && "${zsh_syntax_result}" == "success" && "${fleet_tests_result}" == "success" && "${shellcheck_result}" == "success" ]]; then
echo "🐉 Mac Admin Security Dragon Slain"
exit 0
fi
Expand Down
33 changes: 22 additions & 11 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ Takes precedence over `README.md`, `.github/copilot-instructions.md`, and simila
This file codifies project rules, boundaries, workflows, and repeatable skills. If same correction repeats, formalize it here instead of re-prompting it.

## Project Overview
`SYM-Lite` is macOS-only, root-run zsh workflow for executing approved software and management actions through one swiftDialog-driven experience. Primary artifact: `SYM-Lite.zsh`. Supported operation modes: **interactive** (default) and **silent**. Scope limited to Installomator labels, Jamf policy triggers, and approved Homebrew items.
`SYM-Lite` is macOS-only, root-run zsh workflow for executing approved software and management actions through one swiftDialog-driven experience. Primary artifact: `SYM-Lite.zsh`. Supported operation modes: **interactive** (default) and **silent**. Scope limited to Installomator labels, Jamf policy triggers, approved Homebrew items, and explicitly configured Fleet self-service software.

## Key Commands
- Validate syntax after every Zsh edit: `zsh -n SYM-Lite.zsh`
- Inspect current script version: `rg -n '^scriptVersion=' SYM-Lite.zsh`
- Inspect current item inventories: `rg -n '^(installomatorLabels|jamfPolicyItems|homebrewItems)=\\(' SYM-Lite.zsh`
- Inspect current item inventories: `rg -n '^(installomatorLabels|jamfPolicyItems|homebrewItems|fleetSoftwareItems)=\(' SYM-Lite.zsh`
- Review canonical runtime docs before behavior edits: `sed -n '1,240p' AGENTS.md`

## Agent Workflow
Expand All @@ -30,9 +30,9 @@ This file codifies project rules, boundaries, workflows, and repeatable skills.
Invoke relevant skill name during planning.

### Add New Executable Item Skill
1. Start from matching array format in `installomatorLabels`, `jamfPolicyItems`, or `homebrewItems`.
1. Start from matching array format in `installomatorLabels`, `jamfPolicyItems`, `homebrewItems`, or `fleetSoftwareItems`.
2. Keep item list sorted by display-name intent because UI merges and sorts groups together.
3. Set real `validationPath`; skip logic and Inspect Mode completion depend on it.
3. Set real `validationPath`; skip logic and Inspect Mode completion depend on it. Fleet items may omit the path, particularly for script-only packages; those items must run each time selected and rely on Fleet's install result.
4. Validate affected parsing and execution flow in `SYM-Lite.zsh`.
5. Update `README.md` if user-visible configuration or behavior changed.

Expand All @@ -58,14 +58,14 @@ Invoke relevant skill name during planning.

**Ask before doing**
- Add new production dependencies.
- Run commands that can install software, trigger Jamf policies, update Homebrew metadata, or otherwise mutate host state outside repo.
- Run commands that can install software, request Fleet installs, trigger Jamf policies, update Homebrew metadata, or otherwise mutate host state outside repo.
- Change default operation mode, parameter semantics, logging contract, or restart behavior.
- Rebuild release notes or prepare release versioning not explicitly requested.

**Never do**
- Hardcode secrets, tokens, org-private endpoints, or credentials.
- Modify files outside current task scope without approval.
- Add arbitrary package workflows beyond Jamf triggers, Installomator labels, or explicitly configured Homebrew packages.
- Add arbitrary package workflows beyond Jamf triggers, Installomator labels, explicitly configured Homebrew packages, or explicitly configured Fleet self-service software.
- Break macOS-only or root-run assumptions by accident.

## Source of Truth
Expand All @@ -83,13 +83,14 @@ In scope:
- Installomator label execution
- Jamf policy trigger execution
- approved Homebrew formula and cask execution
- explicitly configured Fleet self-service software execution, including custom packages and script-only packages
- path-based validation, logging, completion reporting, and restart prompts

Out of scope:
- non-macOS support
- non-root execution as primary runtime model
- enrollment, inventory collection strategy, or broad device orchestration
- arbitrary package pipelines outside configured Jamf, Installomator, and Homebrew items
- arbitrary package pipelines outside configured Jamf, Installomator, Homebrew, and Fleet items

## Implementation Priorities
1. Preserve single-script architecture in `SYM-Lite.zsh`.
Expand All @@ -108,18 +109,24 @@ Out of scope:

## Current Runtime Hotspots
- `dialogCheck()` always runs in pre-flight and can auto-install or update swiftDialog from GitHub; blocked network breaks bootstrap.
- Installomator availability is optional for each run; missing or unparsable Installomator filters those labels instead of aborting Jamf or Homebrew execution.
- `validationPath` drives both pre-execution skip logic and Inspect Mode completion detection; wrong path can suppress needed work or hide completion.
- Installomator availability is optional for each run; missing or unparsable Installomator filters those labels instead of aborting Jamf, Homebrew, or Fleet execution.
- `validationPath` drives pre-execution skip logic and path-based completion detection; wrong paths can suppress needed work or hide completion. Fleet items with empty paths never pre-skip; a configured path also requires postvalidation after Fleet success.
- Interactive mode needs active logged-in GUI user and exits after wait window if none appears.
- Homebrew execution runs in logged-in user context even though script itself runs as root.
- Jamf and Homebrew completion remain path-based, not rich progress parsed.
- Fleet support is opt-in and reads the rotating device token from Orbit's `identifier` file for each request. Never add API-user credentials or expose device tokens, raw API responses, or script output in logs or dialog files.
- Fleet request acceptance is not completion. Track the requested install through its outcome; a timeout ends SYM-Lite's wait without cancelling Fleet's operation.
- Fleet execution errors produce exit status `1` after the completion flow. Preserve explicit failure reasons and distinguish confirmed failures from unconfirmed results.
- In mixed Fleet/Installomator sessions, disable Installomator log auto-matching so a matching display name cannot falsely complete a Fleet row.
- Fleet catalog eligibility is checked during execution. Only Fleet-managed/custom/script packages are supported; App Store apps and self-service browser SSO require separate flows.
- Fleet delivery must finish before SYM-Lite waits on further Fleet installs; use a detached launch or separate job to avoid blocking the install queue.

## Repository Rules
- Always run `zsh -n` after modifying Zsh files.
- Do not add new production dependencies without explicit approval.
- Keep durable repo rules near top of this file; avoid timestamps, counters, or ephemeral task notes in stable sections.
- Preserve existing script style unless strong reason exists to refactor.
- Keep `installomatorLabels`, `jamfPolicyItems`, and `homebrewItems` sorted by display-name intent.
- Keep `installomatorLabels`, `jamfPolicyItems`, `homebrewItems`, and `fleetSoftwareItems` sorted by display-name intent.
- If behavior, configuration semantics, or environment assumptions change, update `README.md` in same pass.
- `CHANGELOG.md` is long-term history for released versions.
- `SYM-Lite.zsh` `HISTORY` section should describe current version under development only.
Expand All @@ -138,6 +145,7 @@ Match established `SYM-Lite.zsh` style unless user explicitly asks otherwise.
- Installomator: `"label | Display Name | Validation Path | Icon URL"`
- Jamf: `"trigger | Display Name | Validation Path | Icon URL"`
- Homebrew: `"formula:token"` or `"cask:token"` item id with same four-field layout
- Fleet: `"fleet:<software title ID> | Display Name | Validation Path | Icon URL"`; a validation path is optional
8. Keep silent-mode parsing tolerant of operator input normalization when touching CSV or item ID logic.
9. Prefer degraded-but-continuable warnings over fatal exits unless workflow truly cannot proceed.
10. Keep user-facing strings concise and operator-friendly.
Expand All @@ -150,10 +158,13 @@ Match established `SYM-Lite.zsh` style unless user explicitly asks otherwise.
- Default Installomator path: `/Library/Application Support/AppAutoPatch/Installomator/Installomator.sh`
- Default Jamf binary path: `/usr/local/bin/jamf`
- Homebrew detection prefers `/opt/homebrew/bin/brew`, then `/usr/local/bin/brew`
- Default Fleet Orbit root: `/opt/orbit`; Fleet support starts disabled with no configured items and discovers the server URL unless `fleetURL` is set
- Fleet requires an enrolled agent, a usable device token, and software available to the device through self-service without browser SSO
- Default logging paths: `/var/log/org.churchofjesuschrist.log` and `/var/log/Installomator.log`

## Quality Bar
- Keep pre-flight behavior reliable across missing GUI user, missing swiftDialog, missing Installomator, missing Jamf, and missing Homebrew cases.
- Keep pre-flight behavior reliable across missing GUI user, missing swiftDialog, missing Installomator, missing Jamf, missing Homebrew, and unavailable Fleet cases.
- Verify Fleet changes with mocked requests and responses. Do not request live installs as a test without explicit authorization.
- Keep interactive UX valid: selection dialog, Inspect Mode JSON, command file, completion dialog, restart prompt.
- Keep silent mode deterministic: parameter parsing, item lookup, skip logic, and completion reporting must stay clear.
- Logging must remain structured and useful for operators.
Expand Down
Loading