Skip to content
This repository was archived by the owner on Sep 4, 2026. It is now read-only.
Merged
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
32 changes: 32 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: Bug report
about: Report something the SDK gets wrong
title: ""
labels: "needs triage"
assignees: ""
---

#### What happened

_What the SDK did._

#### What you expected

_What you expected it to do instead._

#### Reproducing it

_The smallest snippet that shows the problem. Please redact tokens._

```go
```

#### Versions

- SDK version (or `firezone.Version`):
- Go version (`go version`):
- Firezone portal: cloud, or self-hosted at version:

#### Anything else

_Error text, the request that failed, whatever else is relevant._
11 changes: 11 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
blank_issues_enabled: true
contact_links:
- name: "Community Support - Discussion Forums"
url: "https://discourse.firez.one"
about: "Ask questions, get help from other Firezone users, and suggest features."
- name: "Community Support - Discord"
url: "https://discord.gg/DY8gxpSgep"
about: "Join discussions, meet other users, and get updates from the Firezone team."
- name: "Report a security vulnerability"
url: "https://github.com/firezone/firezone-go/security/advisories/new"
about: "Please report vulnerabilities privately, not as a public issue."
21 changes: 21 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: Feature request
about: Suggest something the SDK should do
title: ""
labels: "needs triage"
assignees: ""
---

#### What would you like the SDK to do?

_A clear description of the behavior you want._

#### What are you trying to accomplish?

_The underlying goal. This often suggests a better shape for the API
than the one that first comes to mind._

#### Is there an API endpoint behind it?

_If this is about an endpoint the SDK doesn't cover yet, say which one.
Some are deliberately out of scope; see the README._
15 changes: 15 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#### What does this change?

_A short description, and the issue it closes if there is one._

#### Why?

_What problem this solves. If it fixes a bug, what the bug was._

#### Checklist

- [ ] `mise run check` passes
- [ ] `mise run test-acceptance` passes, if this touches the wire
- [ ] `mise run spec-check` passes, if this adds or changes a JSON field
- [ ] `CHANGELOG.md` updated under `Unreleased`, if this is user-visible
- [ ] Exported identifiers have doc comments
7 changes: 7 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ jobs:
- name: Unit tests (-race)
run: mise run test

# The only check that can catch a struct tag the server doesn't
# actually send. It runs against the spec vendored in testdata/,
# so it needs no monorepo checkout for now. In the future the
# spec will be retrieved from a live source.
- name: Check struct tags against the OpenAPI spec
run: mise run spec-check

- name: Scan for known vulnerabilities (govulncheck)
run: mise run vuln

Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
.env
.envrc
/dist/
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Changelog

All notable changes to this project are documented here.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Because this is a client library, "breaking" means a change that stops
existing code compiling or changes what a call does. A new exported
field or method is additive, thus not breaking.

While this project is at 0.x the exported API is not yet frozen:
breaking changes bump the minor version and are listed under
`### Changed`, with a note on what to do about them. From 1.0.0 onward
they will require a new major version.

## [Unreleased]

## [0.1.0] - 2026-09-02

First public release. The API is complete and verified against a live
Firezone portal, but ships as 0.x while it gets real use. See the
versioning note above for what that means for compatibility.

### Added

- Read-write services for Sites, Resources, Policies, Groups, Actors and
Client devices, with Gateways nested under Sites, memberships nested
under Groups, and pool members nested under Resources.
- Read-only services for the five auth provider types and the three
directory connection types.
- Cursor pagination on every list method (`ListOptions` → `Page[T]`).
- Typed errors: `APIError` carrying RFC 9457 problem details, with
`IsNotFound`, `IsValidation`, `IsRateLimited`, `IsForbidden`,
`IsUnauthorized` and `IsConflict` predicates.
- Automatic retry with exponential backoff and jitter on HTTP 429,
honouring `Retry-After`. Configurable via `WithRetry` and
`WithRetryMaxWait`.
- `Null[T]` with `Set` and `Clear`, so nullable fields on merge-patch
update requests can be cleared as well as set.
- `Version`, sent as part of the default `User-Agent`.

### Notes

- `Update` methods send `PATCH`. The API routes `PATCH` and `PUT` to the
same handler, but a partial update is what `PATCH` means, and sending
the matching verb insures against the two ever diverging.
`Memberships.ReplaceAll` and `PoolMembers.ReplaceAll` send `PUT`,
Comment on lines +45 to +48
where the API genuinely distinguishes them, as do `Verify` and
`Unverify`.
- Some endpoints are deliberately not wrapped; the README lists which,
and the `GatewaysService` doc comment explains the Gateway token ones
in particular.

[Unreleased]: https://github.com/firezone/firezone-go/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/firezone/firezone-go/releases/tag/v0.1.0
106 changes: 106 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Contributing

Thanks for your interest in improving the Firezone Go SDK.

## Getting set up

Tool versions come from `.tool-versions`, so local runs and CI can't
drift apart. With [mise](https://mise.jdx.dev) installed:

```bash
mise install
mise run check # everything CI runs, in one shot
```

The SDK has no third-party dependencies — standard library only. Please
keep it that way; a dependency in a client library becomes a dependency
for everyone who imports it.

## Before opening a pull request

```bash
mise run check
```

That runs formatting, `go vet` (including the `integration` and `spec`
build tags), `golangci-lint`, unit tests with `-race`, the OpenAPI spec
checks, `govulncheck`, and a build. Individual tasks are listed by
`mise tasks`.

Two more that CI doesn't run for you:

```bash
mise run test-floor # build + test on the oldest supported Go
mise run test-acceptance # against a real portal - see the README
```

Run the acceptance tests after changing anything that touches the wire.
They are the only tests that can disagree with the SDK about how the
server behaves, and they have caught real bugs that every other check
passed.

## Conventions worth knowing

**Every exported identifier needs a doc comment.** `golangci-lint`
enforces it. This package is meant to be read through `go doc` and
pkg.go.dev.

**JSON struct tags are checked against the OpenAPI spec.** A tag the
server doesn't recognise fails silently at runtime — a response field
decodes as a zero value, and a request field is dropped by the server
without an error. `mise run spec-check` compares the tags against the
spec vendored at `testdata/openapi.json`. Run it whenever you add or
change a field.

**Nullable fields have rules in both directions.** On a merge-patch
update request, a field the spec marks nullable must be `*Null[T]` so it
can be cleared as well as set, and an array field must be `*[]T` so an
empty list can be sent. On a read model, a nullable non-string field
must be a pointer, because `0` and `false` are legitimate values that a
null would be indistinguishable from. Both rules are enforced by the
spec tests.

**Request paths go through `buildPath`, never string concatenation**,
and caller-supplied IDs go through `checkID` first.

**The `go` directive in `go.mod` is the oldest Go this SDK supports**,
not the version we build with. Keep it as low as the code allows —
raising it is a hard requirement on every consumer.

## Updating the vendored OpenAPI spec

```bash
FIREZONE_MONOREPO=/path/to/firezone mise run spec-update
```

The resulting diff is the list of API changes this SDK hasn't accounted
for yet, so it belongs in the same pull request as the code that
responds to it — never as a standalone commit to make CI green.

## Cutting a release

1. Refresh the vendored spec (`mise run spec-update`) and deal with any
diff. Shipping against a stale spec means shipping unverified tags.
2. Update `Version` in `firezone.go`. It is sent in the `User-Agent`, so
it needs to match the tag.
3. Move the `Unreleased` section of `CHANGELOG.md` into a new version
section and update the comparison links at the bottom.
4. `mise run check`, `mise run test-floor`, and `mise run test-acceptance`.
The acceptance run is not optional for a release: it is the only
check that can disagree with the SDK about how the server behaves.
5. Tag `vX.Y.Z` and push the tag. pkg.go.dev picks it up from there;
there are no artifacts to build.

## Versioning

Semantic versioning applies to the exported API. Retyping an existing
exported field or changing what a call does is breaking, even when it is
a bug fix.

**This project is at 0.x.** The exported API is not frozen yet: a
breaking change bumps the minor version (0.1.0 → 0.2.0) and is called
out in the changelog. That is deliberate. The SDK is verified against a
live portal, but it has not yet been through enough sustained real use.

Once the library has seen enough real use and any adjustments have been made
we will move to 1.0.0
Loading
Loading