feat: add boundary premium feature (#21589)

Source code changes:

- Added a wrapper for the boundary subcommand that checks feature
entitlement before executing the underlying command.
- Added a helper that returns the Boundary version using the
runtime/debug package, which reads this information from the go.mod
file.
- Added FeatureBoundary to the corresponding enum.
- Move boundary command from AGPL to enterprise.

`NOTE`: From now on, the Boundary version will be specified in go.mod
instead of being defined in AI modules.
This commit is contained in:
Yevhenii Shcherbina
2026-01-23 12:56:36 -05:00
committed by GitHub
parent b82693d4cc
commit 9b14fd3adc
15 changed files with 624 additions and 51 deletions
-12
View File
@@ -1,12 +0,0 @@
package cli
import (
boundarycli "github.com/coder/boundary/cli"
"github.com/coder/serpent"
)
func (*RootCmd) boundary() *serpent.Command {
cmd := boundarycli.BaseCommand() // Package coder/boundary/cli exports a "base command" designed to be integrated as a subcommand.
cmd.Use += " [args...]" // The base command looks like `boundary -- command`. Serpent adds the flags piece, but we need to add the args.
return cmd
}
-33
View File
@@ -1,33 +0,0 @@
package cli_test
import (
"testing"
"github.com/stretchr/testify/assert"
boundarycli "github.com/coder/boundary/cli"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
// Actually testing the functionality of coder/boundary takes place in the
// coder/boundary repo, since it's a dependency of coder.
// Here we want to test basically that integrating it as a subcommand doesn't break anything.
func TestBoundarySubcommand(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
inv, _ := clitest.New(t, "exp", "boundary", "--help")
pty := ptytest.New(t).Attach(inv)
go func() {
err := inv.WithContext(ctx).Run()
assert.NoError(t, err)
}()
// Expect the --help output to include the short description.
// We're simply confirming that `coder boundary --help` ran without a runtime error as
// a good chunk of serpents self validation logic happens at runtime.
pty.ExpectMatch(boundarycli.BaseCommand().Short)
}
+6 -1
View File
@@ -151,7 +151,6 @@ func (r *RootCmd) AGPLExperimental() []*serpent.Command {
r.promptExample(),
r.rptyCommand(),
r.syncCommand(),
r.boundary(),
}
}
@@ -333,6 +332,12 @@ func (r *RootCmd) Command(subcommands []*serpent.Command) (*serpent.Command, err
// support links.
return
}
if cmd.Name() == "boundary" {
// The boundary command is integrated from the boundary package
// and has YAML-only options (e.g., allowlist from config file)
// that don't have flags or env vars.
return
}
merr = errors.Join(
merr,
xerrors.Errorf("option %q in %q should have a flag or env", opt.Name, cmd.FullName()),
+3
View File
@@ -90,6 +90,7 @@ const (
FeatureManagedAgentLimit FeatureName = "managed_agent_limit"
FeatureWorkspaceExternalAgent FeatureName = "workspace_external_agent"
FeatureAIBridge FeatureName = "aibridge"
FeatureBoundary FeatureName = "boundary"
)
var (
@@ -119,6 +120,7 @@ var (
FeatureManagedAgentLimit,
FeatureWorkspaceExternalAgent,
FeatureAIBridge,
FeatureBoundary,
}
// FeatureNamesMap is a map of all feature names for quick lookups.
@@ -163,6 +165,7 @@ func (n FeatureName) AlwaysEnable() bool {
FeatureMultipleOrganizations: true,
FeatureWorkspacePrebuilds: true,
FeatureWorkspaceExternalAgent: true,
FeatureBoundary: true,
}[n]
}
+5
View File
@@ -1344,6 +1344,11 @@
"description": "Toggle auto-update policy for a workspace",
"path": "reference/cli/autoupdate.md"
},
{
"title": "boundary",
"description": "Network isolation tool for monitoring and restricting HTTP/HTTPS requests",
"path": "reference/cli/boundary.md"
},
{
"title": "coder",
"path": "reference/cli/index.md"
+147
View File
@@ -0,0 +1,147 @@
<!-- DO NOT EDIT | GENERATED CONTENT -->
# boundary
Network isolation tool for monitoring and restricting HTTP/HTTPS requests
## Usage
```console
coder boundary [flags] [args...]
```
## Description
```console
boundary creates an isolated network environment for target processes, intercepting HTTP/HTTPS traffic through a transparent proxy that enforces user-defined allow rules.
```
## Options
### --config
| | |
|-------------|-------------------------------|
| Type | <code>yaml-config-path</code> |
| Environment | <code>$BOUNDARY_CONFIG</code> |
Path to YAML config file.
### --allow
| | |
|-------------|------------------------------|
| Type | <code>string</code> |
| Environment | <code>$BOUNDARY_ALLOW</code> |
Allow rule (repeatable). These are merged with allowlist from config file. Format: "pattern" or "METHOD[,METHOD] pattern".
### --
| | |
|------|---------------------------|
| Type | <code>string-array</code> |
| YAML | <code>allowlist</code> |
Allowlist rules from config file (YAML only).
### --log-level
| | |
|-------------|----------------------------------|
| Type | <code>string</code> |
| Environment | <code>$BOUNDARY_LOG_LEVEL</code> |
| YAML | <code>log_level</code> |
| Default | <code>warn</code> |
Set log level (error, warn, info, debug).
### --log-dir
| | |
|-------------|--------------------------------|
| Type | <code>string</code> |
| Environment | <code>$BOUNDARY_LOG_DIR</code> |
| YAML | <code>log_dir</code> |
Set a directory to write logs to rather than stderr.
### --proxy-port
| | |
|-------------|--------------------------|
| Type | <code>int</code> |
| Environment | <code>$PROXY_PORT</code> |
| YAML | <code>proxy_port</code> |
| Default | <code>8080</code> |
Set a port for HTTP proxy.
### --pprof
| | |
|-------------|------------------------------|
| Type | <code>bool</code> |
| Environment | <code>$BOUNDARY_PPROF</code> |
| YAML | <code>pprof_enabled</code> |
Enable pprof profiling server.
### --pprof-port
| | |
|-------------|-----------------------------------|
| Type | <code>int</code> |
| Environment | <code>$BOUNDARY_PPROF_PORT</code> |
| YAML | <code>pprof_port</code> |
| Default | <code>6060</code> |
Set port for pprof profiling server.
### --configure-dns-for-local-stub-resolver
| | |
|-------------|--------------------------------------------------------------|
| Type | <code>bool</code> |
| Environment | <code>$BOUNDARY_CONFIGURE_DNS_FOR_LOCAL_STUB_RESOLVER</code> |
| YAML | <code>configure_dns_for_local_stub_resolver</code> |
Configure DNS for local stub resolver (e.g., systemd-resolved). Only needed when /etc/resolv.conf contains nameserver 127.0.0.53.
### --jail-type
| | |
|-------------|----------------------------------|
| Type | <code>string</code> |
| Environment | <code>$BOUNDARY_JAIL_TYPE</code> |
| YAML | <code>jail_type</code> |
| Default | <code>nsjail</code> |
Jail type to use for network isolation. Options: nsjail (default), landjail.
### --disable-audit-logs
| | |
|-------------|----------------------------------|
| Type | <code>bool</code> |
| Environment | <code>$DISABLE_AUDIT_LOGS</code> |
| YAML | <code>disable_audit_logs</code> |
Disable sending of audit logs to the workspace agent when set to true.
### --log-proxy-socket-path
| | |
|-------------|----------------------------------------------------------|
| Type | <code>string</code> |
| Environment | <code>$CODER_AGENT_BOUNDARY_LOG_PROXY_SOCKET_PATH</code> |
| Default | <code>/tmp/boundary-audit.sock</code> |
Path to the socket where the boundary log proxy server listens for audit logs.
### --version
| | |
|------|-------------------|
| Type | <code>bool</code> |
Print version information and exit.
+1
View File
@@ -65,6 +65,7 @@ Coder — A tool for provisioning self-hosted development environments with Terr
| [<code>support</code>](./support.md) | Commands for troubleshooting issues with a Coder deployment. |
| [<code>server</code>](./server.md) | Start a Coder server |
| [<code>provisioner</code>](./provisioner.md) | View and manage provisioner daemons and jobs |
| [<code>boundary</code>](./boundary.md) | Network isolation tool for monitoring and restricting HTTP/HTTPS requests |
| [<code>features</code>](./features.md) | List Enterprise features |
| [<code>licenses</code>](./licenses.md) | Add, delete, and list licenses |
| [<code>groups</code>](./groups.md) | Manage groups |
+86
View File
@@ -0,0 +1,86 @@
package cli
import (
"net/http"
"os"
"runtime/debug"
"golang.org/x/xerrors"
boundarycli "github.com/coder/boundary/cli"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
)
func isChild() bool {
return os.Getenv("CHILD") == "true"
}
func getBoundaryVersion() string {
const boundaryModulePath = "github.com/coder/boundary"
buildInfo, ok := debug.ReadBuildInfo()
if !ok {
return "unknown"
}
for _, module := range buildInfo.Deps {
if module.Path == boundaryModulePath {
return module.Version
}
}
return "unknown"
}
func (r *RootCmd) verifyLicense(inv *serpent.Invocation) error {
client, err := r.InitClient(inv)
if err != nil {
return err
}
entitlements, err := client.Entitlements(inv.Context())
if cerr, ok := codersdk.AsError(err); ok && cerr.StatusCode() == http.StatusNotFound {
return xerrors.Errorf("your deployment appears to be an AGPL deployment, so you cannot use the boundary command")
} else if err != nil {
return xerrors.Errorf("failed to get entitlements: %w", err)
}
feature := entitlements.Features[codersdk.FeatureBoundary]
if feature.Entitlement == codersdk.EntitlementNotEntitled {
return xerrors.Errorf("your license is not entitled to use the boundary feature")
}
if !feature.Enabled {
// Feature is entitled but disabled (shouldn't happen for FeatureBoundary
// since it's in AlwaysEnable(), but handle it gracefully).
return xerrors.Errorf("the boundary feature is disabled in your deployment configuration")
}
return nil
}
func (r *RootCmd) boundary() *serpent.Command {
version := getBoundaryVersion()
cmd := boundarycli.BaseCommand(version) // Package coder/boundary/cli exports a "base command" designed to be integrated as a subcommand.
cmd.Use += " [args...]" // The base command looks like `boundary -- command`. Serpent adds the flags piece, but we need to add the args.
// Wrap the handler to check for FeatureBoundary entitlement.
originalHandler := cmd.Handler
cmd.Handler = func(inv *serpent.Invocation) error {
// Boundary re-executes itself with CHILD=true to run the target process
// inside a jailed network namespace. Skip the license check for child
// processes since the parent already verified entitlement.
if isChild() {
return originalHandler(inv)
}
if err := r.verifyLicense(inv); err != nil {
return err
}
// Call the original handler if entitlement check passes.
return originalHandler(inv)
}
return cmd
}
+305
View File
@@ -0,0 +1,305 @@
package cli_test
import (
"net/http"
"net/http/httptest"
"net/http/httputil"
"net/url"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
boundarycli "github.com/coder/boundary/cli"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
"github.com/coder/coder/v2/enterprise/coderd/license"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/coder/v2/testutil"
)
// Actually testing the functionality of coder/boundary takes place in the
// coder/boundary repo, since it's a dependency of coder.
// Here we want to test basically that integrating it as a subcommand doesn't break anything.
func TestBoundarySubcommand(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
inv, _ := newCLI(t, "boundary", "--help")
pty := ptytest.New(t).Attach(inv)
go func() {
err := inv.WithContext(ctx).Run()
assert.NoError(t, err)
}()
// Expect the --help output to include the short description.
// We're simply confirming that `coder boundary --help` ran without a runtime error as
// a good chunk of serpents self validation logic happens at runtime.
pty.ExpectMatch(boundarycli.BaseCommand("dev").Short)
}
func TestBoundaryLicenseVerification(t *testing.T) {
t.Parallel()
t.Run("EntitledAndEnabled", func(t *testing.T) {
t.Parallel()
client, _ := coderdenttest.New(t, &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureBoundary: 1,
},
},
})
inv, conf := newCLI(t, "boundary", "--version")
//nolint:gocritic // requires owner
clitest.SetupConfig(t, client, conf)
ctx := testutil.Context(t, testutil.WaitShort)
err := inv.WithContext(ctx).Run()
// Should succeed - boundary --version should work with valid license.
require.NoError(t, err)
})
t.Run("NotEntitled", func(t *testing.T) {
t.Parallel()
// Create a proxy server that returns entitlements without boundary feature.
client, _ := coderdenttest.New(t, &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
// No FeatureBoundary
},
},
})
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/v2/entitlements" {
res := codersdk.Entitlements{
Features: map[codersdk.FeatureName]codersdk.Feature{},
Warnings: []string{},
Errors: []string{},
HasLicense: true,
Trial: false,
RequireTelemetry: false,
}
// Set boundary to not entitled, all other features to entitled.
for _, feature := range codersdk.FeatureNames {
if feature == codersdk.FeatureBoundary {
// Explicitly set boundary to not entitled.
res.Features[feature] = codersdk.Feature{
Entitlement: codersdk.EntitlementNotEntitled,
Enabled: false,
}
} else {
res.Features[feature] = codersdk.Feature{
Entitlement: codersdk.EntitlementEntitled,
Enabled: true,
}
}
}
httpapi.Write(r.Context(), w, http.StatusOK, res)
return
}
// Otherwise, proxy the request to the real API server.
rp := httputil.NewSingleHostReverseProxy(client.URL)
tp := &http.Transport{}
defer tp.CloseIdleConnections()
rp.Transport = tp
rp.ServeHTTP(w, r)
}))
defer proxy.Close()
proxyURL, err := url.Parse(proxy.URL)
require.NoError(t, err)
proxyClient := codersdk.New(proxyURL)
proxyClient.SetSessionToken(client.SessionToken())
t.Cleanup(proxyClient.HTTPClient.CloseIdleConnections)
inv, conf := newCLI(t, "boundary", "--version")
clitest.SetupConfig(t, proxyClient, conf)
ctx := testutil.Context(t, testutil.WaitShort)
err = inv.WithContext(ctx).Run()
require.Error(t, err)
require.ErrorContains(t, err, "your license is not entitled to use the boundary feature")
})
t.Run("FeatureDisabled", func(t *testing.T) {
t.Parallel()
// Create a proxy server that returns entitlements with boundary disabled.
client, _ := coderdenttest.New(t, &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureBoundary: 1,
},
},
})
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/v2/entitlements" {
res := codersdk.Entitlements{
Features: map[codersdk.FeatureName]codersdk.Feature{},
Warnings: []string{},
Errors: []string{},
HasLicense: true,
Trial: false,
RequireTelemetry: false,
}
for _, feature := range codersdk.FeatureNames {
if feature == codersdk.FeatureBoundary {
// Feature is entitled but disabled.
res.Features[feature] = codersdk.Feature{
Entitlement: codersdk.EntitlementEntitled,
Enabled: false,
}
} else {
res.Features[feature] = codersdk.Feature{
Entitlement: codersdk.EntitlementEntitled,
Enabled: true,
}
}
}
httpapi.Write(r.Context(), w, http.StatusOK, res)
return
}
// Otherwise, proxy the request to the real API server.
rp := httputil.NewSingleHostReverseProxy(client.URL)
tp := &http.Transport{}
defer tp.CloseIdleConnections()
rp.Transport = tp
rp.ServeHTTP(w, r)
}))
defer proxy.Close()
proxyURL, err := url.Parse(proxy.URL)
require.NoError(t, err)
proxyClient := codersdk.New(proxyURL)
proxyClient.SetSessionToken(client.SessionToken())
t.Cleanup(proxyClient.HTTPClient.CloseIdleConnections)
inv, conf := newCLI(t, "boundary", "--version")
clitest.SetupConfig(t, proxyClient, conf)
ctx := testutil.Context(t, testutil.WaitShort)
err = inv.WithContext(ctx).Run()
require.Error(t, err)
require.ErrorContains(t, err, "the boundary feature is disabled in your deployment configuration")
})
t.Run("AGPLDeployment", func(t *testing.T) {
t.Parallel()
// Create an AGPL server (no enterprise features).
client := coderdtest.New(t, &coderdtest.Options{})
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/v2/entitlements" {
// AGPL deployments return 404 for entitlements endpoint.
w.WriteHeader(http.StatusNotFound)
return
}
// Otherwise, proxy the request to the real API server.
rp := httputil.NewSingleHostReverseProxy(client.URL)
tp := &http.Transport{}
defer tp.CloseIdleConnections()
rp.Transport = tp
rp.ServeHTTP(w, r)
}))
defer proxy.Close()
proxyURL, err := url.Parse(proxy.URL)
require.NoError(t, err)
proxyClient := codersdk.New(proxyURL)
proxyClient.SetSessionToken(client.SessionToken())
t.Cleanup(proxyClient.HTTPClient.CloseIdleConnections)
inv, conf := newCLI(t, "boundary", "--version")
clitest.SetupConfig(t, proxyClient, conf)
ctx := testutil.Context(t, testutil.WaitShort)
err = inv.WithContext(ctx).Run()
require.Error(t, err)
require.ErrorContains(t, err, "your deployment appears to be an AGPL deployment")
})
}
// TestBoundaryChildProcessSkipsCheck verifies that when CHILD=true, the license
// check is skipped. This simulates boundary re-executing itself to run the
// target process. We use a proxy that would fail the license check to verify
// it's skipped.
func TestBoundaryChildProcessSkipsCheck(t *testing.T) {
// Cannot use t.Parallel() with t.Setenv().
client, _ := coderdenttest.New(t, &coderdenttest.Options{
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
// No FeatureBoundary - would normally fail
},
},
})
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api/v2/entitlements" {
// Return not entitled for boundary - this would normally cause failure.
res := codersdk.Entitlements{
Features: map[codersdk.FeatureName]codersdk.Feature{},
Warnings: []string{},
Errors: []string{},
HasLicense: true,
Trial: false,
RequireTelemetry: false,
}
for _, feature := range codersdk.FeatureNames {
if feature == codersdk.FeatureBoundary {
res.Features[feature] = codersdk.Feature{
Entitlement: codersdk.EntitlementNotEntitled,
Enabled: false,
}
} else {
res.Features[feature] = codersdk.Feature{
Entitlement: codersdk.EntitlementEntitled,
Enabled: true,
}
}
}
httpapi.Write(r.Context(), w, http.StatusOK, res)
return
}
// Otherwise, proxy the request to the real API server.
rp := httputil.NewSingleHostReverseProxy(client.URL)
tp := &http.Transport{}
defer tp.CloseIdleConnections()
rp.Transport = tp
rp.ServeHTTP(w, r)
}))
defer proxy.Close()
proxyURL, err := url.Parse(proxy.URL)
require.NoError(t, err)
proxyClient := codersdk.New(proxyURL)
proxyClient.SetSessionToken(client.SessionToken())
t.Cleanup(proxyClient.HTTPClient.CloseIdleConnections)
inv, conf := newCLI(t, "boundary", "--version")
clitest.SetupConfig(t, proxyClient, conf)
// Set CHILD=true to simulate boundary re-execution. This should skip the
// license check, so the command should succeed even though the proxy would
// return "not entitled".
t.Setenv("CHILD", "true")
ctx := testutil.Context(t, testutil.WaitShort)
err = inv.WithContext(ctx).Run()
// Should succeed because license check is skipped for child processes.
require.NoError(t, err)
}
+1
View File
@@ -18,6 +18,7 @@ func (r *RootCmd) enterpriseOnly() []*serpent.Command {
agplcli.ExperimentalCommand(append(r.AGPLExperimental(), r.enterpriseExperimental()...)),
// New commands that don't exist in AGPL:
r.boundary(),
r.workspaceProxy(),
r.features(),
r.licenses(),
+2
View File
@@ -15,6 +15,8 @@ USAGE:
SUBCOMMANDS:
aibridge Manage AI Bridge.
boundary Network isolation tool for monitoring and restricting
HTTP/HTTPS requests
external-workspaces Create or manage external workspaces
features List Enterprise features
groups Manage groups
+57
View File
@@ -0,0 +1,57 @@
coder v0.0.0-devel
USAGE:
coder boundary [flags] [args...]
Network isolation tool for monitoring and restricting HTTP/HTTPS requests
boundary creates an isolated network environment for target processes,
intercepting HTTP/HTTPS traffic through a transparent proxy that enforces
user-defined allow rules.
OPTIONS:
--allow string, $BOUNDARY_ALLOW
Allow rule (repeatable). These are merged with allowlist from config
file. Format: "pattern" or "METHOD[,METHOD] pattern".
string-array
Allowlist rules from config file (YAML only).
--config yaml-config-path, $BOUNDARY_CONFIG
Path to YAML config file.
--configure-dns-for-local-stub-resolver bool, $BOUNDARY_CONFIGURE_DNS_FOR_LOCAL_STUB_RESOLVER
Configure DNS for local stub resolver (e.g., systemd-resolved). Only
needed when /etc/resolv.conf contains nameserver 127.0.0.53.
--disable-audit-logs bool, $DISABLE_AUDIT_LOGS
Disable sending of audit logs to the workspace agent when set to true.
--jail-type string, $BOUNDARY_JAIL_TYPE (default: nsjail)
Jail type to use for network isolation. Options: nsjail (default),
landjail.
--log-dir string, $BOUNDARY_LOG_DIR
Set a directory to write logs to rather than stderr.
--log-level string, $BOUNDARY_LOG_LEVEL (default: warn)
Set log level (error, warn, info, debug).
--log-proxy-socket-path string, $CODER_AGENT_BOUNDARY_LOG_PROXY_SOCKET_PATH (default: /tmp/boundary-audit.sock)
Path to the socket where the boundary log proxy server listens for
audit logs.
--pprof bool, $BOUNDARY_PPROF
Enable pprof profiling server.
--pprof-port int, $BOUNDARY_PPROF_PORT (default: 6060)
Set port for pprof profiling server.
--proxy-port int, $PROXY_PORT (default: 8080)
Set a port for HTTP proxy.
--version bool
Print version information and exit.
———
Run `coder --help` for a list of global options.
+3 -2
View File
@@ -453,7 +453,7 @@ require (
google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
howett.net/plist v1.0.0 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.73 // indirect
kernel.org/pub/linux/libs/security/libcap/psx v1.2.77 // indirect
sigs.k8s.io/yaml v1.5.0 // indirect
)
@@ -475,7 +475,7 @@ require (
github.com/coder/agentapi-sdk-go v0.0.0-20250505131810-560d1d88d225
github.com/coder/aibridge v0.3.1-0.20260121122740-e164b504fc52
github.com/coder/aisdk-go v0.0.9
github.com/coder/boundary v0.0.1-alpha
github.com/coder/boundary v0.6.0
github.com/coder/preview v1.0.4
github.com/danieljoos/wincred v1.2.3
github.com/dgraph-io/ristretto/v2 v2.3.0
@@ -541,6 +541,7 @@ require (
github.com/jackmordaunt/icns/v3 v3.0.1 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
github.com/landlock-lsm/go-landlock v0.0.0-20251103212306-430f8e5cd97c // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
+6 -3
View File
@@ -931,8 +931,8 @@ github.com/coder/aibridge v0.3.1-0.20260121122740-e164b504fc52 h1:UcsOXQH881tXPp
github.com/coder/aibridge v0.3.1-0.20260121122740-e164b504fc52/go.mod h1:x45BE/NNDesDN1eWy4bsg81QsL6ou7xXPIeQr0ePETQ=
github.com/coder/aisdk-go v0.0.9 h1:Vzo/k2qwVGLTR10ESDeP2Ecek1SdPfZlEjtTfMveiVo=
github.com/coder/aisdk-go v0.0.9/go.mod h1:KF6/Vkono0FJJOtWtveh5j7yfNrSctVTpwgweYWSp5M=
github.com/coder/boundary v0.0.1-alpha h1:6shUQ2zkrWrfbgVcqWvpV2ibljOQvPvYqTctWBkKoUA=
github.com/coder/boundary v0.0.1-alpha/go.mod h1:d1AMFw81rUgrGHuZzWdPNhkY0G8w7pvLNLYF0e3ceC4=
github.com/coder/boundary v0.6.0 h1:DfYVBIH8/6EBfg9I0qz7rX2jo+4blUx4P4amd13nib8=
github.com/coder/boundary v0.6.0/go.mod h1:jEXVbTGQP9JFoXkyzsnitj2rsWJuTt+VVej1Yzr2CkQ=
github.com/coder/bubbletea v1.2.2-0.20241212190825-007a1cdb2c41 h1:SBN/DA63+ZHwuWwPHPYoCZ/KLAjHv5g4h2MS4f2/MTI=
github.com/coder/bubbletea v1.2.2-0.20241212190825-007a1cdb2c41/go.mod h1:I9ULxr64UaOSUv7hcb3nX4kowodJCVS7vt7VVJk/kW4=
github.com/coder/clistat v1.2.0 h1:37KJKqiCllJsRvWqTHf3qiLIXX0JB6oqE5oxcqgdLkY=
@@ -1544,6 +1544,8 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/kyokomi/emoji/v2 v2.2.13 h1:GhTfQa67venUUvmleTNFnb+bi7S3aocF7ZCXU9fSO7U=
github.com/kyokomi/emoji/v2 v2.2.13/go.mod h1:JUcn42DTdsXJo1SWanHh4HKDEyPaR5CqkmoirZZP9qE=
github.com/landlock-lsm/go-landlock v0.0.0-20251103212306-430f8e5cd97c h1:QcKqiunpt7hooa/xIx0iyepA6Cs2BgKexaYOxHvHNCs=
github.com/landlock-lsm/go-landlock v0.0.0-20251103212306-430f8e5cd97c/go.mod h1:stwyhp9tfeEy3A4bRJLdOEvjW/CetRJg/vcijNG8M5A=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
@@ -2847,8 +2849,9 @@ k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJ
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.73 h1:Th2b8jljYqkyZKS3aD3N9VpYsQpHuXLgea+SZUIfODA=
kernel.org/pub/linux/libs/security/libcap/cap v1.2.73/go.mod h1:hbeKwKcboEsxARYmcy/AdPVN11wmT/Wnpgv4k4ftyqY=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.73 h1:SEAEUiPVylTD4vqqi+vtGkSnXeP2FcRO3FoZB1MklMw=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.73/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.77 h1:Z06sMOzc0GNCwp6efaVrIrz4ywGJ1v+DP0pjVkOfDuA=
kernel.org/pub/linux/libs/security/libcap/psx v1.2.77/go.mod h1:+l6Ee2F59XiJ2I6WR5ObpC1utCQJZ/VLsEbQCD8RG24=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
+2
View File
@@ -2110,6 +2110,7 @@ export type FeatureName =
| "advanced_template_scheduling"
| "appearance"
| "audit_log"
| "boundary"
| "browser_only"
| "connection_log"
| "control_shared_ports"
@@ -2136,6 +2137,7 @@ export const FeatureNames: FeatureName[] = [
"advanced_template_scheduling",
"appearance",
"audit_log",
"boundary",
"browser_only",
"connection_log",
"control_shared_ports",