Changelog: July 2026

This month's theme is governance. We introduced data classification as first-class metadata on every workspace — declared at provision time, color-coded in the UI, and pushed into your Terraform runs as cloud tags and labels. Alongside it: organization-owned API keys built to outlive personnel changes, and richer cloud-specific tagging on ns_workspace. We also shipped nullstone apps release to take infra and app code live in one command, made variable and secret editing far nicer in the UI, and added a GCP BigQuery + Datastream data-pipeline set to the catalog. Read on for details.

July 1, 2026
Brad Sickles
Brad Sickles
Co-founder and CEO
Changelog: July 2026

Overview

# Product

- Data Classification
- One-Command Releases
- Organization API Keys
- Type-Aware Variable Editing
- Managed Secrets in the UI
- Cloud-Specific Tags & Labels
- Cron Trigger Awareness
- Fixes & Smaller Improvements

## Data Classification

We introduced **data classification** as governance metadata on workspaces — datastore-first, but available on any block or workspace type.

- Declared at provision time and carried as workspace metadata
- **Color-coded in the UI** so sensitive workspaces are obvious at a glance
- Editable in both the UI and your IaC
- Fed into Terraform runs, so modules can stamp AWS tags, GCP labels, Azure tags, and Kubernetes labels from the classification

This first version is metadata and visibility only — no access-control enforcement yet.

## `nullstone apps release`

`nullstone apps release` collapses infra-update and deploy into a single workflow. The intent is simple: say "make my infra and app code live," and let Nullstone pick the optimal, most reliable path.

By default:

- Runs an infra-update if the workspace has outstanding changes
- Runs a deploy if the app version has changed
- Does the right thing when only one — or neither — has changed

We also fixed a related bug: when `release` performed an infra-update followed by a deploy, the app version recorded on the workspace wasn't being updated, so a subsequent `nullstone run` could execute stale app code. The workspace version now reflects exactly what was released.

## Organization API Keys

API keys are no longer tied to an individual person. Previously every key belonged to a human `User`, so removing that person from Nullstone silently broke any key they had minted — including the ones living in CI/CD pipelines.

Org architects can now mint **organization-owned API keys** that survive personnel changes. Each key carries its own scope — which stacks it can reach and the role it holds on each — so a CI key can be granted exactly the access it needs and nothing more.

## Type-Aware Variable Editing

We replaced the "edit every variable at once" flow with a **per-variable** edit experience, and the value inputs are now aware of the variable's Terraform type:

- Toggles for `bool`
- Add/remove editors for `list(...)` and `map(...)`
- Plain inputs where that's all that's needed

The same components power both the block workspace **Configuration** tab and app variable editing.

## Managed Secrets in the UI

Secrets stored in AWS Secrets Manager or GCP Secret Manager used to be wired into an app by pasting a `{{ secret(<id>) }}` string as an env var value. In the dashboard that value was just `sensitive` — rendered as `••••••••••` with no hint that it pointed at a managed secret, and no way to interact with it.

You can now see when an env var references a managed secret, and view, set, reset, or pick that secret directly from the app's env vars in the UI.

## Cloud-Specific Tags & Labels

The `ns_workspace` data source previously exposed a single, AWS-shaped `tags` map. We've expanded that into cloud-provider-specific attributes so each cloud gets a correctly-formatted set:

- `aws_tags` — follows AWS tag conventions (PascalCase keys, matching the existing `tags`)
- `gcp_labels` — follows GCP label constraints

Modules can now tag and label resources with the shape each cloud actually expects — and it's the same plumbing data classification rides on.

## Cron Trigger Awareness

Apps triggered on a schedule can now tell, from inside app code:

- Whether an execution was a **manual** run or a **cron-triggered** run
- **Which** schedule fired it, when more than one cron trigger is attached to the same app

Nullstone injects these values into the execution for you to read. The primary use case is ECS/Fargate apps, but the contract spans every app pattern that supports cron triggers.

## Fixes & Small Improvements

- **More reliable Terraform/OpenTofu runs under load** — we split the heavy Terraform/OpenTofu execution work (`init`/`plan`/`apply`) onto its own dedicated runner, isolated from lightweight orchestration. A burst of infra runs can no longer starve everything sharing the same worker, keeping both infra runs and everyday operations responsive.
- **Clearer `nullstone push` permission errors** — a user without permission to read a workspace's sensitive outputs previously got a deeply-nested AWS SDK error (`static credentials are empty` / `Internal Server Error`) that gave no hint at the real cause. The error now points at the RBAC redaction instead of the AWS internals.
- **GKE job executions now appear in Deployment Status** — GKE job apps could show "No job executions found" even when their CronJob had spawned executions. The Deployment Status view now surfaces them correctly.
- **`nullstone modules new|register --if=missing`** — a new flag that no-ops gracefully (exit 0) when the module already exists, instead of erroring, making module registration safe to run repeatedly in CI.

# Catalog

### GCP BigQuery & Datastream

A new set of modules for standing up an analytics pipeline on GCP:

- **`gcp-bigquery-dataset`** — create a BigQuery dataset as a Nullstone datastore, with location inferred from the environment region and configurable table expiration and destroy behavior
- **`gcp-existing-bigquery-dataset`** — register an existing BigQuery dataset as a datastore (reads only, creates no infrastructure) while sharing the same output contract
- **`gcp-datastream-postgres-bigquery`** — replicate PostgreSQL into BigQuery via GCP Datastream

### Cloud Run Cron Triggers

The new **`gcp-cloudrun-cron-trigger`** module lets Cloud Run jobs fire on a schedule (Cloud Scheduler → Cloud Run Jobs), bringing them to parity with the cron trigger patterns already available on ECS/Fargate, Lambda, and EKS/GKE.

### API Gateway Authorizers

Both API Gateway modules gained an optional authorizer that stays fully backward-compatible — when the connection is absent, routes remain open exactly as before:

- **`aws-api-gateway-http-api`** — optional **JWT** authorizer via a `jwt-authorizer` connection
- **`aws-api-gateway-rest-api`** — optional **Cognito** user-pool authorizer via a `cognito-user-pool` connection

### Cloud SQL Safeguards

New backward-compatible flags (all default `false`) for protecting production databases:

- **`gcp-cloudsql-postgres`** — `point_in_time_recovery_enabled` and `deletion_protection_enabled`
- **`gcp-cloudsql-mysql`** — `deletion_protection_enabled`

### Extensible GKE OTEL Collector

The `gcp-gke-otel-collector` module now supports pluggable telemetry destinations through an optional `extender` connection. A separate block can register extra OTEL config fragments — Langfuse, Datadog, Honeycomb, and the like — that the collector merges at runtime, so adding a sink no longer means forking the module.