courier

command module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

README

Build status Go Reference Quality Gate Status

This repository is experimental; it's based on ideas or techniques not fully hardened or finalized, so please use caution. Best efforts have been made to ensure safety guards are in place.

Courier

Courier pull exports your Openlane organization's controls, policies, and other objects into structured YAML and markdown files, and apply pushes your edits back through the Openlane API. The goals, broadly:

  • Allow for bulk edits of control or policy language in a git-friendly fashion
  • Create the basis for a git-flow signature with Openlane so that you can lean into git's branch protection, pull request flow, diff abilities
  • Use traditional text, markdown editors for those friendly to the style
  • Provide non-UI methods for performing cohesive data exports and/or re-imports

Non-goals:

  • Providing 100% seamless capabilities with what the Openlane Console provides for rich-text editing, comments / discussions, etc. (table coloring, font, etc., are not preserved and this repo doesn't attempt it)
  • Bloating the scope to include every object in Openlane's graphql schema
  • Turning courier into some terraform-esk frankenstein that haunts all our dreams
  • Making apply destructive (e.g. making the non-presence of records, or the presence of empty fields, create destructive actions)

Installation

Clone this repository and build the binary:

task build

This produces a courier binary in the repository root. You can also install with Go:

go install github.com/theopenlane/courier@latest

Or with Homebrew:

brew install theopenlane/tap/courier

Signed release archives are available on the releases page.

How it works

Run courier pull to export your organization's controls, control mappings, and policies into these files. Edit them, open a pull request, and run courier apply after merge to push the changes back. Git is the change record in both directions: pull rewrites the files from the server's current state, so git diff after a pull shows what changed in Openlane, and your pull request shows what you are changing.

Controls are matched by their Openlane ID, with a refCode fallback when an ID is not present. Policies are matched by ID alone, carried in the manifest or the document frontmatter, because policy names are not unique. Entries without a match are created: new control IDs arrive on the next pull, and a created policy's ID is written into its document frontmatter so a repeated apply updates the policy instead of duplicating it.

Both pull and apply accept --controls or --policies to operate on one object kind; with neither flag they operate on both.

Controls

Each entry in controls.yaml represents one organization control, the specific thing you implemented to meet a standard's control:

- id: CTL_01J...
  refCode: CC1.1.3
  title: ""
  description: New hires are required to complete an acknowledgment form upon hire.
  category: Control Environment
  subcategory: Integrity and Ethics
  mappedControls:
    SOC 2:
      - CC1.1

The title, description, category, and subcategory fields are rendered even when they hold no value, so completing a sparse control means filling in a stubbed field rather than adding one. An empty field is treated as unmanaged: courier leaves the corresponding value in Openlane alone rather than clearing it. Rich-text descriptions authored in the Openlane editor export as plain text.

The mappedControls block groups the reference codes of controls this record maps to by their framework, the same shape as the satisfies map in policy frontmatter. Reference codes resolve case-insensitively within their framework, and references to your own controls without a framework group under the custom key.

A refCode that matches nothing is skipped with a warning, so you can apply a control inventory before the referenced framework has been cloned. New entries create mappings in Openlane; entries removed from your files don't get removed in the API.

Policies

Each entry in policies.yaml points at a markdown document that holds the policy content:

- id: PLC_01J...
  name: Application Security Policy
  policyType: Security
  markdownPath: policies/application-security-policy.md
  tags:
    - application
    - security

The document carries YAML frontmatter followed by the policy body:

---
openlane_id: PLC_01J...
title: Application Security Policy
status: PUBLISHED
tags:
  - application
  - security
revision: v1.0.0
satisfies:
  SOC 2:
    - CC6.2
---

## Purpose and Scope
...

The satisfies map lists the framework controls the policy satisfies, grouped by framework short name. On apply, courier uploads the whole document and the Openlane server parses the frontmatter, so the file you review in a pull request is the source the platform ingests. On pull, bodies render from the server's stored content: markdown that courier uploaded comes back as written, and edits made in the Openlane rich-text editor arrive as converted markdown.

Editor validation

The jsonscehmas for controls.yaml and policies.yaml live in schema/, generated from the same types courier validates with at apply time. Point your editor's YAML language server at them to get autocomplete and inline validation while editing:

# yaml-language-server: $schema=https://raw.githubusercontent.com/theopenlane/courier/main/schema/controls.json

Configuration

Settings merge from three sources, and later sources win: the config file, COURIER_-prefixed environment variables, and command-line flags.

The config file defaults to config/.config.yaml relative to the working directory, or pass --config path.

host: https://api.theopenlane.io
token: tolp_...
organization-id: ""              # only needed for multi-organization tokens
dir: .                           # workspace directory

Contributing

See the contributing guide for more information.

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
Package cmd implements the courier command line interface
Package cmd implements the courier command line interface
Package constants contains constants used throughout the application
Package constants contains constants used throughout the application
internal
jsonschema command
Package main generates the courier schema artifacts: the configuration JSON schema, the commented example configuration file, the example environment file, and the document schemas for controls.yaml and policies.yaml used by editors to validate store files
Package main generates the courier schema artifacts: the configuration JSON schema, the commented example configuration file, the example environment file, and the document schemas for controls.yaml and policies.yaml used by editors to validate store files
pkg
controlfile
Package controlfile defines the structured files used to export organization-owned controls and internal policies out of Openlane and load them back in via the API: a controls.yaml inventory, a policies.yaml manifest, and one markdown document with YAML frontmatter per policy.
Package controlfile defines the structured files used to export organization-owned controls and internal policies out of Openlane and load them back in via the API: a controls.yaml inventory, a policies.yaml manifest, and one markdown document with YAML frontmatter per policy.
engine
Package engine implements the export and reconcile logic behind the courier binary: pulling organization controls and mappings out of the Openlane API into controlfile documents, diffing local documents against the live system, and applying creates and updates back through the API
Package engine implements the export and reconcile logic behind the courier binary: pulling organization controls and mappings out of the Openlane API into controlfile documents, diffing local documents against the live system, and applying creates and updates back through the API

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL