m5c workspaces and packages
Workspaces and packages organize Mach5 app source before it is built, tested, lowered, and deployed.
Use a workspace for a multi-package source tree. Use an app package to declare one deployable app’s contracts, feature gates, resources, and tests.
Workspace
A workspace is rooted by m5c.workspace.yaml.
kind: Mach5Workspace
version: 1
packages:
- packages/contracts
- packages/modules
- packages/security-analytics
The equivalent object form is also supported:
packages:
- path: packages/contracts
- path: packages/security-analytics
Workspace fields
| Field | Required | Meaning |
|---|---|---|
kind | Yes | Must be Mach5Workspace. |
version | Yes | Must be 1. |
packages | Recommended | Package or source roots, relative to the workspace file. |
Use a workspace when a project has more than one package, shared contracts, shared source modules, or app packages that should validate together.
Create a starter workspace:
m5c init apps/security-analytics
Package layout
A common layout is:
apps/security-analytics/
m5c.workspace.yaml
packages/
contracts/
identity-authentication/
contract.yaml
repository-activity/
contract.yaml
modules/
okta-system-log/
module.yaml
mappings/
system-log-auth.yaml
security-analytics/
package.yaml
detection_families/
identity-access.yaml
detections/
okta-password-spray.yaml
detection_imports/
sigma/
import.yaml
sources/
okta-failed-login.yml
resources/
security-soc-app-poc/
tests/
expected_findings/
okta-password-spray.yaml
lowered/
m5c discovers known files by convention:
| Convention | Concept |
|---|---|
m5c.workspace.yaml | Workspace definition. |
package.yaml | App package definition. |
contract.yaml | Data contract. |
module.yaml | Data module. |
Any *.yaml under a mappings directory | Contract mapping. |
Any *.yaml under packages/**/detection_families | Detection family. |
Any *.yaml under packages/**/detections | Detection. |
import.yaml under packages/**/detection_imports/** | Detection import. |
Any *.yaml under an expected_findings directory | Expected-finding test file. |
App package
An AppPackage declares app metadata, required contracts, preferred contracts, feature gates, resources, and tests.
kind: AppPackage
metadata:
name: security-analytics
owner: mach5
spec:
version: 0.1.0
display_name: Mach5 Security Analytics
package_card: ./package-card.yaml
requires:
contracts:
security.raw_event.v1: ">=1.0.0 <2.0.0"
identity.authentication_event.v1: ">=1.0.0 <2.0.0"
repo.activity.v1: ">=1.0.0 <2.0.0"
preferred:
contracts:
endpoint.process_activity.v1: ">=1.0.0 <2.0.0"
cloud.audit_activity.v1: ">=1.0.0 <2.0.0"
feature_gates:
okta_identity_detections:
requires:
- identity.authentication_event.v1.principal_available
- identity.authentication_event.v1.raw_evidence_reference_available
github_repository_detections:
requires:
- repo.activity.v1.actor_available
- repo.activity.v1.repository_available
resources:
- ../../bundles/okta-starter/bundle.yaml
- ./resources/security-soc-app-poc
tests:
- ./tests/lowering/*.yaml
App package fields
| Field | Required | Meaning |
|---|---|---|
kind | Yes | Must be AppPackage. |
metadata.name | Yes | Package name. |
metadata.owner | Optional | Package owner. |
spec.version | Yes | Semver package version. |
spec.display_name | Optional | Human-readable package name. |
spec.package_card | Optional | Relative path to package-card metadata. |
spec.requires.contracts | Recommended | Required contract names and semver ranges. |
spec.preferred.contracts | Optional | Optional/preferred contract names and semver ranges. |
spec.feature_gates | Optional | Named gates controlled by required capabilities. |
spec.resources | Optional | Bundle/resource paths included during lowering and deployment workflows. |
spec.tests | Optional | Test globs or paths used by package workflows. |
Required and preferred contracts
Contract maps use contract names as keys and semver requirements as values.
requires:
contracts:
identity.authentication_event.v1: ">=1.0.0 <2.0.0"
preferred:
contracts:
cloud.audit_activity.v1: ">=1.0.0 <2.0.0"
requires means the package expects that contract for its main functionality. preferred means the package can use the contract when available.
m5c validate checks that referenced contracts exist locally and that the version range is valid. It also warns when a required contract has no local provider module.
Feature gates
Feature gates name optional app or detection areas and list required capabilities.
feature_gates:
okta_identity_detections:
requires:
- identity.authentication_event.v1.principal_available
- identity.authentication_event.v1.raw_evidence_reference_available
Detections can reference a feature gate:
spec:
feature_gate: okta_identity_detections
Use feature gates when only part of an app should be enabled for a given contract/module coverage set.
Resources
Resources point to deployable bundle inputs or resource directories.
resources:
- ../../bundles/okta-starter/bundle.yaml
- ./resources/security-soc-app-poc
Paths are resolved relative to package.yaml. Validation warns when a referenced resource path does not exist yet.
Package cards
package_card points to package-level metadata used for presentation, review, or catalog workflows.
package_card: ./package-card.yaml
Validation checks that the referenced file exists.
Build and inspect
Build creates a deterministic local artifact.
m5c build apps/security-analytics --out dist
m5c inspect dist/security-analytics
Inspect prints a JSON summary of the package artifact, including included concepts, checksums, provenance, and digest.
Validate, test, lower
Use this loop while authoring:
m5c validate apps/security-analytics --workspace --offline
m5c test apps/security-analytics --workspace
m5c lower apps/security-analytics --dev --out /tmp/m5c-lowered
Validation checks workspace paths, document kinds, semver versions, contract references, package-card paths, and resource references.
Common mistakes
| Mistake | Fix |
|---|---|
Setting workspace version to another value | Use version: 1. |
| Listing a package path that does not exist | Fix the relative path from m5c.workspace.yaml. |
Using aliases under requires.contracts | Use contract names as keys and semver ranges as values. |
| Forgetting a local provider module for a required contract | Add a DataModule or make the contract preferred instead. |
| Referencing feature gate capabilities that contracts do not define | Add the capability to the contract or correct the reference. |
Moving resources without updating spec.resources | Keep resource paths relative to package.yaml. |
Best practices
- Keep shared contracts in a separate package root.
- Keep provider modules separate from app packages.
- Keep app packages focused on one deployable app or solution.
- Use semver ranges consistently across packages, modules, and detections.
- Use feature gates for optional contract coverage.
- Run validate and test at the workspace root before building or lowering.