From 5e403b8da37d7cdcf4cf4e725a839a5ca4b16053 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:15:53 -0400 Subject: [PATCH 01/14] Initial commit --- go.mod | 17 + go.sum | 90 +++++ internal/commands/api/api.go | 2 + internal/commands/api/schema.go | 147 +++++++ internal/commands/api/schema_eval_test.go | 134 +++++++ internal/commands/api/schema_search.go | 112 ++++++ internal/commands/api/schema_search_bluge.go | 130 ++++++ .../commands/api/schema_search_helpers.go | 204 ++++++++++ internal/commands/api/schema_spec.go | 373 ++++++++++++++++++ internal/commands/api/schema_test.go | 193 +++++++++ 10 files changed, 1402 insertions(+) create mode 100644 internal/commands/api/schema.go create mode 100644 internal/commands/api/schema_eval_test.go create mode 100644 internal/commands/api/schema_search.go create mode 100644 internal/commands/api/schema_search_bluge.go create mode 100644 internal/commands/api/schema_search_helpers.go create mode 100644 internal/commands/api/schema_spec.go create mode 100644 internal/commands/api/schema_test.go diff --git a/go.mod b/go.mod index ca94e8c..cd60ecd 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.25.5 require ( github.com/MakeNowJust/heredoc/v2 v2.0.1 + github.com/blugelabs/bluge v0.2.2 github.com/dustin/go-humanize v1.0.1 github.com/hashicorp/cli v1.1.7 github.com/hashicorp/go-hclog v1.6.3 @@ -32,20 +33,35 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect + github.com/RoaringBitmap/roaring v0.9.4 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect github.com/armon/go-radix v1.0.0 // indirect + github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/bgentry/speakeasy v0.2.0 // indirect + github.com/bits-and-blooms/bitset v1.2.0 // indirect + github.com/blevesearch/go-porterstemmer v1.0.3 // indirect + github.com/blevesearch/mmap-go v1.0.4 // indirect + github.com/blevesearch/segment v0.9.0 // indirect + github.com/blevesearch/snowballstem v0.9.0 // indirect + github.com/blevesearch/vellum v1.0.7 // indirect + github.com/blugelabs/bluge_segment_api v0.2.0 // indirect + github.com/blugelabs/ice v1.0.0 // indirect + github.com/blugelabs/ice/v2 v2.0.1 // indirect + github.com/caio/go-tdigest v3.1.0+incompatible // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc // indirect github.com/fatih/color v1.18.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/snappy v0.0.1 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/huandu/xstrings v1.5.0 // indirect + github.com/klauspost/compress v1.15.2 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -58,6 +74,7 @@ require ( github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/mschoch/smat v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/shopspring/decimal v1.4.0 // indirect diff --git a/go.sum b/go.sum index 045509c..dbfa0bc 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -8,29 +9,73 @@ github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7r github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/RoaringBitmap/gocroaring v0.4.0/go.mod h1:NieMwz7ZqwU2DD73/vvYwv7r4eWBKuPVSXZIpsaMwCI= +github.com/RoaringBitmap/real-roaring-datasets v0.0.0-20190726190000-eb7c87156f76/go.mod h1:oM0MHmQ3nDsq609SS36p+oYbRi16+oVvU2Bw4Ipv0SE= +github.com/RoaringBitmap/roaring v0.9.1/go.mod h1:h1B7iIUOmnAeb5ytYMvnHJwxMc6LUrwBnzXWRuqTQUc= +github.com/RoaringBitmap/roaring v0.9.4 h1:ckvZSX5gwCRaJYBNe7syNawCU5oruY9gQmjXlp4riwo= +github.com/RoaringBitmap/roaring v0.9.4/go.mod h1:icnadbWcNyfEHlYdr+tDlOTih1Bf/h+rzPpv4sbomAA= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f h1:y06x6vGnFYfXUoVMbrcP1Uzpj4JG01eB5vRps9G8agM= +github.com/axiomhq/hyperloglog v0.0.0-20191112132149-a4c4c47bc57f/go.mod h1:2stgcRjl6QmW+gU2h5E7BQXg4HU0gzxKWDuT5HviN9s= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/bgentry/speakeasy v0.2.0 h1:tgObeVOf8WAvtuAX6DhJ4xks4CFNwPDZiqzGqIHE51E= github.com/bgentry/speakeasy v0.2.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo= +github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M= +github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA= +github.com/blevesearch/mmap-go v1.0.3/go.mod h1:pYvKl/grLQrBxuaRYgoTssa4rVujYYeenDp++2E+yvs= +github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= +github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= +github.com/blevesearch/segment v0.9.0 h1:5lG7yBCx98or7gK2cHMKPukPZ/31Kag7nONpoBt22Ac= +github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ= +github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s= +github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs= +github.com/blevesearch/vellum v1.0.5/go.mod h1:atE0EH3fvk43zzS7t1YNdNC7DbmcC3uz+eMD5xZ2OyQ= +github.com/blevesearch/vellum v1.0.7 h1:+vn8rfyCRHxKVRgDLeR0FAXej2+6mEb5Q15aQE/XESQ= +github.com/blevesearch/vellum v1.0.7/go.mod h1:doBZpmRhwTsASB4QdUZANlJvqVAUdUyX0ZK7QJCTeBE= +github.com/blugelabs/bluge v0.2.2 h1:gat8CqE6P6tOgeX30XGLOVNTC26cpM2RWVcreXWtYcM= +github.com/blugelabs/bluge v0.2.2/go.mod h1:am1LU9jS8dZgWkRzkGLQN3757EgMs3upWrU2fdN9foE= +github.com/blugelabs/bluge_segment_api v0.2.0 h1:cCX1Y2y8v0LZ7+EEJ6gH7dW6TtVTW4RhG0vp3R+N2Lo= +github.com/blugelabs/bluge_segment_api v0.2.0/go.mod h1:95XA+ZXfRj/IXADm7gZ+iTcWOJPg5jQTY1EReIzl3LA= +github.com/blugelabs/ice v1.0.0 h1:um7wf9e6jbkTVCrOyQq3tKK43fBMOvLUYxbj3Qtc4eo= +github.com/blugelabs/ice v1.0.0/go.mod h1:gNfFPk5zM+yxJROhthxhVQYjpBO9amuxWXJQ2Lo+IbQ= +github.com/blugelabs/ice/v2 v2.0.1 h1:mzHbntLjk2v7eDRgoXCgzOsPKN1Tenu9Svo6l9cTLS4= +github.com/blugelabs/ice/v2 v2.0.1/go.mod h1:QxAWSPNwZwsIqS25c3lbIPFQrVvT1sphf5x5DfMLH5M= +github.com/caio/go-tdigest v3.1.0+incompatible h1:uoVMJ3Q5lXmVLCCqaMGHLBWnbGoN6Lpu7OAUPR60cds= +github.com/caio/go-tdigest v3.1.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc h1:8WFBn63wegobsYAX0YjD+8suexZDga5CctH4CCTx2+8= +github.com/dgryski/go-metro v0.0.0-20180109044635-280f6062b5bc/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -38,6 +83,9 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -56,18 +104,27 @@ github.com/hashicorp/go-tfe v1.78.1-0.20260414223040-554d4064682a h1:K5t3L7CDC3g github.com/hashicorp/go-tfe v1.78.1-0.20260414223040-554d4064682a/go.mod h1:NCc9n8HN05g6Bu5v0a3JhkOoWN42DF/Jk0nDQSaZwFI= github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA= github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/hcl/v2 v2.24.0 h1:2QJdZ454DSsYGoaE6QheQZjtKZSUs9Nh2izTWiwQxvE= github.com/hashicorp/hcl/v2 v2.24.0/go.mod h1:oGoO1FIQYfn/AgyOhlg9qLC6/nOJPX3qGbkZpYAcqfM= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v1.7.6/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/klauspost/compress v1.15.2 h1:3WH+AG7s2+T8o3nrM/8u2rdqUEcQhmga7smjrT41nAw= +github.com/klauspost/compress v1.15.2/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353 h1:X/79QL0b4YJVO5+OsPH9rF2u428CIrGL/jLmPsoOQQ4= +github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U= github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= @@ -98,16 +155,20 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= +github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -119,19 +180,30 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/std-uritemplate/std-uritemplate/go/v2 v2.0.8 h1:gMBdYMTHt2mmTdXW8YfvRjRUZ0GhyGV+IqSH9H15bGw= github.com/std-uritemplate/std-uritemplate/go/v2 v2.0.8/go.mod h1:Z5KcoM0YLC7INlNhEezeIZ0TZNYf7WSNO0Lvah4DSeQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/zclconf/go-cty v1.16.3 h1:osr++gw2T61A8KVYHoQiFbFd1Lh3JOCXc/jFLJXKTxk= github.com/zclconf/go-cty v1.16.3/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= @@ -144,34 +216,52 @@ go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWv go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo= golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.7.0 h1:Hdks0L0hgznZLG9nzXb8vZ0rRvqNvAcgAp84y7Mwkgw= +gonum.org/v1/gonum v0.7.0/go.mod h1:L02bwd0sqlsvRv41G7wGWFCsVNZFv/k1xzGIxeANHGM= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/commands/api/api.go b/internal/commands/api/api.go index 00ec6df..bd2b67a 100644 --- a/internal/commands/api/api.go +++ b/internal/commands/api/api.go @@ -277,6 +277,8 @@ func NewCmdAPI(ctx *cmd.Context) *cmd.Command { }, } + cmd.AddChild(NewCmdAPISchema(ctx)) + return cmd } diff --git a/internal/commands/api/schema.go b/internal/commands/api/schema.go new file mode 100644 index 0000000..31f4b8a --- /dev/null +++ b/internal/commands/api/schema.go @@ -0,0 +1,147 @@ +package api + +import ( + "encoding/json" + "fmt" + + "github.com/hashicorp/tfcloud/internal/pkg/cmd" + "github.com/hashicorp/tfcloud/internal/pkg/heredoc" + "github.com/hashicorp/tfcloud/internal/pkg/render" +) + +type schemaOperation struct { + OperationID string + Method string + Path string + Tags []string + Summary string +} + +type schemaSearcher interface { + Search(query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) +} + +var ( + loadSchemaOperationsForSearch = cachedSchemaOperations + loadSchemaDocumentForGet = cachedSchemaDocument + schemaOperationSearcher schemaSearcher = hybridSchemaSearcher{} +) + +func NewCmdAPISchema(ctx *cmd.Context) *cmd.Command { + c := &cmd.Command{ + Name: "schema", + ShortHelp: "Search and inspect API operations", + NoAuthRequired: true, + LongHelp: heredoc.New(ctx.IO).Must(` + The {{ template "mdCodeOrBold" "tfcloud api schema" }} command group lets you search + for API operations from the OpenAPI spec and inspect a single operation schema. + `), + } + + c.AddChild(newCmdAPISchemaSearch(ctx)) + c.AddChild(newCmdAPISchemaGet(ctx)) + + return c +} + +func newCmdAPISchemaSearch(ctx *cmd.Context) *cmd.Command { + return &cmd.Command{ + Name: "search", + ShortHelp: "Search API operations", + NoAuthRequired: true, + LongHelp: heredoc.New(ctx.IO).Must(` + Search API operations from the OpenAPI spec. Results are ranked by Bluge and + rendered as a compact table when possible. + `), + Args: cmd.PositionalArguments{ + Args: []cmd.PositionalArgument{{ + Name: "QUERY", + Documentation: "The search query to match against API operations.", + Repeatable: true, + }}, + }, + Examples: []cmd.Example{{ + Preamble: "Search for workspace operations", + Command: "$ tfcloud api schema search workspace", + }}, + RunF: func(_ *cmd.Command, args []string) error { + operations, err := loadSchemaOperationsForSearch() + if err != nil { + return err + } + + results, err := schemaOperationSearcher.Search(joinSchemaQuery(args), operations, maxSchemaSearchResults) + if err != nil { + return err + } + + body, err := schemaSearchJSONAPIResponse(results) + if err != nil { + return err + } + + table, ok, err := render.JSONAPITable(body) + if err != nil { + return err + } + if ok { + _, _ = ctx.IO.Out().Write([]byte(table)) + return nil + } + + _, _ = ctx.IO.Out().Write(body) + return nil + }, + } +} + +func newCmdAPISchemaGet(ctx *cmd.Context) *cmd.Command { + return &cmd.Command{ + Name: "get", + ShortHelp: "Show one API operation schema", + NoAuthRequired: true, + LongHelp: heredoc.New(ctx.IO).Must(` + Show a trimmed OpenAPI document for a single operationId. + `), + Args: cmd.PositionalArguments{ + Args: []cmd.PositionalArgument{{ + Name: "OPERATION_ID", + Documentation: "The exact OpenAPI operationId to inspect.", + }}, + }, + Examples: []cmd.Example{{ + Preamble: "Inspect the getWorkspace operation", + Command: "$ tfcloud api schema get getWorkspace", + }}, + RunF: func(_ *cmd.Command, args []string) error { + document, err := loadSchemaDocumentForGet() + if err != nil { + return err + } + + operationDocument, err := schemaOperationDocument(document, args[0]) + if err != nil { + return err + } + + body, err := json.MarshalIndent(operationDocument, "", " ") + if err != nil { + return fmt.Errorf("marshal operation schema: %w", err) + } + + _, _ = ctx.IO.Out().Write(append(body, '\n')) + return nil + }, + } +} + +func joinSchemaQuery(args []string) string { + if len(args) == 0 { + return "" + } + query := args[0] + for i := 1; i < len(args); i++ { + query += " " + args[i] + } + return query +} diff --git a/internal/commands/api/schema_eval_test.go b/internal/commands/api/schema_eval_test.go new file mode 100644 index 0000000..2068e26 --- /dev/null +++ b/internal/commands/api/schema_eval_test.go @@ -0,0 +1,134 @@ +package api + +import ( + "encoding/json" + "fmt" + "strings" + "testing" +) + +type schemaSearchFixture struct { + name string + query string + wantTop3 []string + operations []schemaOperation +} + +func representativeSchemaSearchFixtures() []schemaSearchFixture { + return []schemaSearchFixture{ + { + name: "workspace query", + query: "workspace", + wantTop3: []string{"getWorkspace", "listWorkspaces"}, + operations: testSchemaOperations, + }, + { + name: "variable query", + query: "variable", + wantTop3: []string{"createWorkspaceVar", "listWorkspaceVars"}, + operations: testSchemaOperations, + }, + { + name: "run query", + query: "run", + wantTop3: []string{"getRun"}, + operations: testSchemaOperations, + }, + } +} + +func TestRepresentativeSchemaQueriesStayWithinResource(t *testing.T) { + t.Parallel() + + for _, fixture := range representativeSchemaSearchFixtures() { + fixture := fixture + t.Run(fixture.name, func(t *testing.T) { + t.Parallel() + + results, err := schemaOperationSearcher.Search(fixture.query, fixture.operations, 3) + if err != nil { + t.Fatal(err) + } + if len(results) == 0 { + t.Fatal("got no results") + } + + got := resultIDs(results) + for _, want := range fixture.wantTop3 { + if !containsOperation(got, want) { + t.Fatalf("expected %q in top results, got %v", want, got) + } + } + }) + } +} + +func TestHybridSchemaSearcherLimitsAndShapesResults(t *testing.T) { + t.Parallel() + + operations := make([]schemaOperation, 0, 12) + for i := 0; i < 12; i++ { + operations = append(operations, schemaOperation{ + OperationID: fmt.Sprintf("getWorkspace%c", 'A'+i), + Method: "GET", + Path: "/workspaces/{workspace_id}", + Tags: []string{"workspaces"}, + Summary: "Get Workspace", + }) + } + + results, err := schemaOperationSearcher.Search("workspace", operations, maxSchemaSearchResults) + if err != nil { + t.Fatal(err) + } + if len(results) != maxSchemaSearchResults { + t.Fatalf("got %d results, want %d", len(results), maxSchemaSearchResults) + } + + body, err := schemaSearchJSONAPIResponse(results) + if err != nil { + t.Fatal(err) + } + + var payload map[string]any + if err := json.Unmarshal(body, &payload); err != nil { + t.Fatal(err) + } + data, ok := payload["data"].([]any) + if !ok || len(data) != maxSchemaSearchResults { + t.Fatalf("unexpected payload shape: %#v", payload) + } +} + +func TestSchemaSearchSummary(t *testing.T) { + t.Parallel() + + fixtures := representativeSchemaSearchFixtures() + rows := make([]string, 0, len(fixtures)+1) + rows = append(rows, fmt.Sprintf("%-18s %s", "query", "top results")) + + for _, fixture := range fixtures { + results, err := schemaOperationSearcher.Search(fixture.query, fixture.operations, maxSchemaSearchResults) + if err != nil { + t.Fatalf("query=%q error: %v", fixture.query, err) + } + rows = append(rows, fmt.Sprintf("%-18s %s", fixture.name, strings.Join(resultIDs(results[:minInt(len(results), 3)]), ", "))) + } + + t.Log("\n" + strings.Join(rows, "\n")) +} + +func resultIDs(results []schemaSearchResult) []string { + ids := make([]string, 0, len(results)) + for _, result := range results { + ids = append(ids, result.Operation.OperationID) + } + return ids +} + +func minInt(a, b int) int { + if a < b { + return a + } + return b +} diff --git a/internal/commands/api/schema_search.go b/internal/commands/api/schema_search.go new file mode 100644 index 0000000..7e1683d --- /dev/null +++ b/internal/commands/api/schema_search.go @@ -0,0 +1,112 @@ +package api + +import ( + "encoding/json" + "fmt" + "sort" + "strings" +) + +const maxSchemaSearchResults = 10 + +type schemaSearchResult struct { + Operation schemaOperation + Confidence float64 + ResourceKey string +} + +type hybridSchemaSearcher struct{} + +func (s hybridSchemaSearcher) Search(query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) { + candidateLimit := limit * 3 + if candidateLimit < 10 { + candidateLimit = 10 + } + if candidateLimit > len(operations) { + candidateLimit = len(operations) + } + + results, err := blugeRetrieve(query, operations, candidateLimit) + if err != nil { + return nil, err + } + return filterSchemaResultsByResource(parseSchemaSearchIntent(query), results, limit), nil +} + +func filterSchemaResultsByResource(intent schemaSearchIntent, results []schemaSearchResult, limit int) []schemaSearchResult { + if limit <= 0 || limit > len(results) { + limit = len(results) + } + + for i := range results { + results[i].ResourceKey = resourceKeyForOperation(intent.Resources, results[i].Operation) + } + + hasResource := false + for _, result := range results { + if result.ResourceKey != "" { + hasResource = true + break + } + } + + filtered := make([]schemaSearchResult, 0, len(results)) + for _, result := range results { + if hasResource && result.ResourceKey == "" { + continue + } + filtered = append(filtered, result) + } + + sort.SliceStable(filtered, func(i, j int) bool { + if filtered[i].Confidence != filtered[j].Confidence { + return filtered[i].Confidence > filtered[j].Confidence + } + if filtered[i].Operation.OperationID != filtered[j].Operation.OperationID { + return filtered[i].Operation.OperationID < filtered[j].Operation.OperationID + } + if filtered[i].Operation.Method != filtered[j].Operation.Method { + return filtered[i].Operation.Method < filtered[j].Operation.Method + } + return filtered[i].Operation.Path < filtered[j].Operation.Path + }) + + if len(filtered) > limit { + filtered = filtered[:limit] + } + return filtered +} + +func resourceKeyForOperation(resources []string, operation schemaOperation) string { + operationSet := tokenSet(normalizeTokens(splitCamelCase(operation.OperationID))) + pathSet := tokenSet(normalizeTokens(tokenize(operation.Path))) + tagSet := tokenSet(normalizeTokens(tokenize(strings.Join(operation.Tags, " ")))) + resource := matchedSchemaResource(resources, operationSet, pathSet, tagSet) + if resource == "" { + return "" + } + if len(resources) == 1 && isNestedSubresourceOperation(resource, operation) { + return "" + } + return resource +} + +func schemaSearchJSONAPIResponse(results []schemaSearchResult) ([]byte, error) { + data := make([]map[string]any, 0, len(results)) + for _, result := range results { + data = append(data, map[string]any{ + "id": strings.ToLower(result.Operation.OperationID), + "type": "api-operations", + "attributes": map[string]any{ + "operation-id": result.Operation.OperationID, + "method": result.Operation.Method, + "path": result.Operation.Path, + "summary": result.Operation.Summary, + "confidence": fmt.Sprintf("%.2f", result.Confidence), + }, + }) + } + + payload := map[string]any{"data": data} + return json.Marshal(payload) +} diff --git a/internal/commands/api/schema_search_bluge.go b/internal/commands/api/schema_search_bluge.go new file mode 100644 index 0000000..02b5757 --- /dev/null +++ b/internal/commands/api/schema_search_bluge.go @@ -0,0 +1,130 @@ +package api + +import ( + "context" + "strconv" + "strings" + + "github.com/blugelabs/bluge" +) + +func blugeRetrieve(query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) { + if limit <= 0 || limit > len(operations) { + limit = len(operations) + } + + writer, err := bluge.OpenWriter(bluge.InMemoryOnlyConfig()) + if err != nil { + return nil, err + } + defer writer.Close() + + byID := make(map[string]schemaOperation, len(operations)) + for i, operation := range operations { + id := strconv.Itoa(i) + byID[id] = operation + if err := writer.Update(bluge.Identifier(id), blugeDocumentForOperation(id, operation)); err != nil { + return nil, err + } + } + + reader, err := writer.Reader() + if err != nil { + return nil, err + } + defer reader.Close() + + searchQuery := blugeQueryForIntent(parseSchemaSearchIntent(query)) + request := bluge.NewTopNSearch(limit, searchQuery) + iterator, err := reader.Search(context.Background(), request) + if err != nil { + return nil, err + } + + results := make([]schemaSearchResult, 0, limit) + match, err := iterator.Next() + for err == nil && match != nil { + id := "" + err = match.VisitStoredFields(func(field string, value []byte) bool { + if field == "_id" { + id = string(value) + } + return true + }) + if err != nil { + return nil, err + } + operation, ok := byID[id] + if ok { + results = append(results, schemaSearchResult{ + Operation: operation, + Confidence: match.Score, + }) + } + match, err = iterator.Next() + } + if err != nil { + return nil, err + } + return results, nil +} + +func blugeDocumentForOperation(id string, operation schemaOperation) *bluge.Document { + tokens := strings.Join(normalizeTokens(splitCamelCase(operation.OperationID)), " ") + pathTokens := strings.Join(normalizeTokens(tokenize(operation.Path)), " ") + tagTokens := strings.Join(normalizeTokens(tokenize(strings.Join(operation.Tags, " "))), " ") + doc := bluge.NewDocument(id). + AddField(bluge.NewTextField("operation_id", operation.OperationID).StoreValue()). + AddField(bluge.NewTextField("operation_tokens", tokens)). + AddField(bluge.NewTextField("summary", operation.Summary)). + AddField(bluge.NewTextField("path_tokens", pathTokens)). + AddField(bluge.NewTextField("tag_tokens", tagTokens)). + AddField(bluge.NewKeywordField("method", strings.ToUpper(operation.Method))). + AddField(bluge.NewStoredOnlyField("path", []byte(operation.Path))) + return doc +} + +func blugeQueryForIntent(intent schemaSearchIntent) bluge.Query { + clauses := make([]bluge.Query, 0, len(intent.Tokens)+4) + for _, token := range intent.Tokens { + clauses = append(clauses, + bluge.NewMatchQuery(token).SetField("operation_id"), + bluge.NewMatchQuery(token).SetField("operation_tokens"), + bluge.NewMatchQuery(token).SetField("summary"), + bluge.NewMatchQuery(token).SetField("path_tokens"), + bluge.NewMatchQuery(token).SetField("tag_tokens"), + ) + } + + if intent.Verb != "" { + if method := preferredMethodForVerb(intent.Verb); method != "" { + clauses = append(clauses, bluge.NewTermQuery(method).SetField("method")) + } + } + + if len(clauses) == 0 { + return bluge.NewMatchAllQuery() + } + + query := bluge.NewBooleanQuery() + for _, clause := range clauses { + query.AddShould(clause) + } + query.SetMinShould(1) + return query +} + +func preferredMethodForVerb(verb string) string { + switch verb { + case "create", "cancel": + return "POST" + case "get", "list": + return "GET" + case "delete": + return "DELETE" + case "update": + return "PATCH" + default: + return "" + } +} diff --git a/internal/commands/api/schema_search_helpers.go b/internal/commands/api/schema_search_helpers.go new file mode 100644 index 0000000..92ded16 --- /dev/null +++ b/internal/commands/api/schema_search_helpers.go @@ -0,0 +1,204 @@ +package api + +import ( + "strings" + "unicode" +) + +type schemaSearchIntent struct { + Tokens []string + Verb string + Resources []string +} + +func matchedSchemaResource(resources []string, operationSet, pathSet, tagSet map[string]struct{}) string { + if len(resources) == 0 { + return "" + } + + for _, resource := range resources { + if resource == "" { + continue + } + if _, ok := tagSet[resource]; ok { + return resource + } + } + for _, resource := range resources { + if resource == "" { + continue + } + if _, ok := pathSet[resource]; ok { + return resource + } + } + for _, resource := range resources { + if resource == "" { + continue + } + if _, ok := operationSet[resource]; ok { + return resource + } + } + return "" +} + +func parseSchemaSearchIntent(query string) schemaSearchIntent { + tokens := normalizeTokens(tokenize(query)) + resources := make([]string, 0, len(tokens)) + verb := "" + + for _, token := range tokens { + if canonical := canonicalVerb(token); canonical != "" && verb == "" { + verb = canonical + continue + } + resources = append(resources, token) + } + + return schemaSearchIntent{ + Tokens: tokens, + Verb: verb, + Resources: resources, + } +} + +func isNestedSubresourceOperation(resource string, operation schemaOperation) bool { + if resource == "" { + return false + } + segments := pathSegments(operation.Path) + for i := 0; i < len(segments)-2; i++ { + if normalizeToken(segments[i]) != resource || !isPathParameter(segments[i+1]) { + continue + } + if !isPathParameter(segments[i+2]) { + return true + } + } + return false +} + +func pathSegments(path string) []string { + trimmed := strings.Trim(path, "/") + if trimmed == "" { + return nil + } + return strings.Split(trimmed, "/") +} + +func isPathParameter(segment string) bool { + return strings.HasPrefix(segment, "{") && strings.HasSuffix(segment, "}") +} + +func tokenize(input string) []string { + fields := strings.FieldsFunc(strings.ToLower(input), func(r rune) bool { + return !unicode.IsLetter(r) && !unicode.IsNumber(r) + }) + tokens := make([]string, 0, len(fields)) + for _, field := range fields { + if field != "" { + tokens = append(tokens, field) + } + } + return tokens +} + +func splitCamelCase(input string) []string { + if input == "" { + return nil + } + + var tokens []string + var current []rune + for i, r := range input { + if i > 0 && unicode.IsUpper(r) && len(current) > 0 { + tokens = append(tokens, strings.ToLower(string(current))) + current = current[:0] + } + current = append(current, r) + } + if len(current) > 0 { + tokens = append(tokens, strings.ToLower(string(current))) + } + for i, token := range tokens { + tokens[i] = splitOperationToken(token) + } + return tokens +} + +func splitOperationToken(token string) string { + switch token { + case "var", "vars": + return "variable" + default: + return token + } +} + +func normalizeTokens(tokens []string) []string { + normalized := make([]string, 0, len(tokens)) + seen := make(map[string]struct{}, len(tokens)) + for _, token := range tokens { + normalizedToken := normalizeToken(token) + if normalizedToken == "" { + continue + } + if _, ok := seen[normalizedToken]; ok { + continue + } + seen[normalizedToken] = struct{}{} + normalized = append(normalized, normalizedToken) + } + return normalized +} + +func normalizeToken(token string) string { + if token == "" { + return "" + } + + switch token { + case "a", "an", "the", "to", "for", "of", "in", "on", "with", "me", "please": + return "" + case "add", "new": + return "create" + case "show", "fetch", "read", "find": + return "get" + case "all", "browse": + return "list" + case "remove", "destroy": + return "delete" + case "edit", "set", "modify": + return "update" + case "stop", "abort": + return "cancel" + case "vars", "var", "variables": + return "variable" + } + + if strings.HasSuffix(token, "ies") && len(token) > 3 { + return token[:len(token)-3] + "y" + } + if strings.HasSuffix(token, "s") && len(token) > 3 && !strings.HasSuffix(token, "ss") { + return token[:len(token)-1] + } + return token +} + +func canonicalVerb(token string) string { + switch token { + case "create", "get", "list", "delete", "cancel", "update": + return token + default: + return "" + } +} + +func tokenSet(tokens []string) map[string]struct{} { + set := make(map[string]struct{}, len(tokens)) + for _, token := range tokens { + set[token] = struct{}{} + } + return set +} diff --git a/internal/commands/api/schema_spec.go b/internal/commands/api/schema_spec.go new file mode 100644 index 0000000..be10990 --- /dev/null +++ b/internal/commands/api/schema_spec.go @@ -0,0 +1,373 @@ +package api + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "runtime" + "sort" + "strings" + "sync" +) + +type openAPISpec struct { + Paths map[string]json.RawMessage `json:"paths"` +} + +type openAPIOperation struct { + OperationID string `json:"operationId"` + Summary string `json:"summary"` + Description string `json:"description"` + Tags []string `json:"tags"` +} + +var ( + schemaOperationsOnce sync.Once + schemaOperationsCache []schemaOperation + schemaOperationsErr error + schemaDocumentOnce sync.Once + schemaDocumentCache map[string]any + schemaDocumentErr error +) + +func cachedSchemaOperations() ([]schemaOperation, error) { + schemaOperationsOnce.Do(func() { + specPath, err := defaultOpenAPISpecPath() + if err != nil { + schemaOperationsErr = err + return + } + schemaOperationsCache, schemaOperationsErr = loadSchemaOperationsFromSpec(specPath) + }) + return schemaOperationsCache, schemaOperationsErr +} + +func cachedSchemaDocument() (map[string]any, error) { + schemaDocumentOnce.Do(func() { + specPath, err := defaultOpenAPISpecPath() + if err != nil { + schemaDocumentErr = err + return + } + schemaDocumentCache, schemaDocumentErr = loadSchemaDocumentFromSpec(specPath) + }) + return schemaDocumentCache, schemaDocumentErr +} + +func loadSchemaDocumentFromSpec(specPath string) (map[string]any, error) { + data, err := os.ReadFile(specPath) + if err != nil { + return nil, fmt.Errorf("read OpenAPI spec %q: %w", specPath, err) + } + + var document map[string]any + if err := json.Unmarshal(data, &document); err != nil { + return nil, fmt.Errorf("parse OpenAPI spec %q: %w", specPath, err) + } + + return document, nil +} + +func loadSchemaOperationsFromSpec(specPath string) ([]schemaOperation, error) { + data, err := os.ReadFile(specPath) + if err != nil { + return nil, fmt.Errorf("read OpenAPI spec %q: %w", specPath, err) + } + + var spec openAPISpec + if err := json.Unmarshal(data, &spec); err != nil { + return nil, fmt.Errorf("parse OpenAPI spec %q: %w", specPath, err) + } + + operations := make([]schemaOperation, 0, len(spec.Paths)) + for path, rawPathItem := range spec.Paths { + var methods map[string]json.RawMessage + if err := json.Unmarshal(rawPathItem, &methods); err != nil { + return nil, fmt.Errorf("parse OpenAPI path item %q: %w", path, err) + } + + for method, rawOperation := range methods { + if !isHTTPMethod(method) { + continue + } + + var operation openAPIOperation + if err := json.Unmarshal(rawOperation, &operation); err != nil { + return nil, fmt.Errorf("parse OpenAPI operation %s %s: %w", strings.ToUpper(method), path, err) + } + if operation.OperationID == "" { + continue + } + + summary := strings.TrimSpace(operation.Summary) + if summary == "" { + summary = strings.TrimSpace(operation.Description) + } + + operations = append(operations, schemaOperation{ + OperationID: operation.OperationID, + Method: strings.ToUpper(method), + Path: path, + Tags: operation.Tags, + Summary: summary, + }) + } + } + + sort.Slice(operations, func(i, j int) bool { + if operations[i].OperationID != operations[j].OperationID { + return operations[i].OperationID < operations[j].OperationID + } + if operations[i].Method != operations[j].Method { + return operations[i].Method < operations[j].Method + } + return operations[i].Path < operations[j].Path + }) + + if len(operations) == 0 { + return nil, fmt.Errorf("no API operations found in OpenAPI spec %q", specPath) + } + + return operations, nil +} + +func defaultOpenAPISpecPath() (string, error) { + _, filename, _, ok := runtime.Caller(0) + if !ok { + return "", fmt.Errorf("resolve schema command source path") + } + + repoRoot := filepath.Clean(filepath.Join(filepath.Dir(filename), "..", "..", "..")) + goModPath := filepath.Join(repoRoot, "go.mod") + candidates := []string{filepath.Join(repoRoot, "openapi", "spec.json")} + + if replaceTarget, err := goModReplaceTarget(goModPath, "github.com/hashicorp/go-tfe"); err == nil && replaceTarget != "" { + if !filepath.IsAbs(replaceTarget) { + replaceTarget = filepath.Join(repoRoot, replaceTarget) + } + candidates = append(candidates, filepath.Join(replaceTarget, "openapi", "spec.json")) + } + + candidates = append(candidates, + filepath.Join(repoRoot, "..", "go-tfe", "openapi", "spec.json"), + filepath.Join(filepath.Dir(repoRoot), "go-tfe", "openapi", "spec.json"), + "/Users/shweta.murali/go-tfe/openapi/spec.json", + ) + + for _, candidate := range candidates { + if _, err := os.Stat(candidate); err == nil { + return candidate, nil + } + } + + return "", fmt.Errorf("could not locate an OpenAPI spec; checked %s", strings.Join(candidates, ", ")) +} + +func schemaOperationDocument(spec map[string]any, operationID string) (map[string]any, error) { + pathValue, ok := spec["paths"].(map[string]any) + if !ok { + return nil, fmt.Errorf("OpenAPI spec does not contain a valid paths object") + } + + path, method, operation, err := findSchemaOperation(pathValue, operationID) + if err != nil { + return nil, err + } + + resolved := dereferenceSchemaOperation(operation, spec, map[string]bool{}) + result := map[string]any{ + "paths": map[string]any{ + path: map[string]any{ + strings.ToLower(method): resolved, + }, + }, + } + if version, ok := spec["openapi"]; ok { + result["openapi"] = version + } + return result, nil +} + +func dereferenceSchemaOperation(operation map[string]any, root map[string]any, refsInProgress map[string]bool) map[string]any { + resolved := make(map[string]any, len(operation)) + for key, value := range operation { + if key == "responses" { + resolved[key] = cloneValue(value) + continue + } + resolved[key] = dereferenceOpenAPIValue(value, root, refsInProgress) + } + return resolved +} + +func findSchemaOperation(paths map[string]any, operationID string) (string, string, map[string]any, error) { + var caseInsensitiveMatch struct { + path string + method string + operation map[string]any + found bool + } + + for path, rawPathItem := range paths { + methods, ok := rawPathItem.(map[string]any) + if !ok { + continue + } + for method, rawOperation := range methods { + if !isHTTPMethod(method) { + continue + } + operation, ok := rawOperation.(map[string]any) + if !ok { + continue + } + currentID, _ := operation["operationId"].(string) + if currentID == operationID { + return path, strings.ToUpper(method), operation, nil + } + if strings.EqualFold(currentID, operationID) { + if caseInsensitiveMatch.found { + return "", "", nil, fmt.Errorf("multiple operations match %q; use exact operationId", operationID) + } + caseInsensitiveMatch = struct { + path string + method string + operation map[string]any + found bool + }{path: path, method: strings.ToUpper(method), operation: operation, found: true} + } + } + } + + if caseInsensitiveMatch.found { + return caseInsensitiveMatch.path, caseInsensitiveMatch.method, caseInsensitiveMatch.operation, nil + } + + return "", "", nil, fmt.Errorf("operation %q not found", operationID) +} + +func dereferenceOpenAPIValue(value any, root map[string]any, refsInProgress map[string]bool) any { + switch typed := value.(type) { + case map[string]any: + if ref, ok := typed["$ref"].(string); ok && strings.HasPrefix(ref, "#/") { + if refsInProgress[ref] { + return cloneMap(typed) + } + resolvedValue, err := resolveJSONPointer(root, ref) + if err == nil { + refsInProgress[ref] = true + resolved := dereferenceOpenAPIValue(resolvedValue, root, refsInProgress) + delete(refsInProgress, ref) + if resolvedMap, ok := resolved.(map[string]any); ok { + merged := cloneMap(resolvedMap) + for key, item := range typed { + if key == "$ref" { + continue + } + merged[key] = dereferenceOpenAPIValue(item, root, refsInProgress) + } + return merged + } + if len(typed) == 1 { + return resolved + } + } + } + + resolved := make(map[string]any, len(typed)) + for key, item := range typed { + resolved[key] = dereferenceOpenAPIValue(item, root, refsInProgress) + } + return resolved + case []any: + resolved := make([]any, 0, len(typed)) + for _, item := range typed { + resolved = append(resolved, dereferenceOpenAPIValue(item, root, refsInProgress)) + } + return resolved + default: + return value + } +} + +func resolveJSONPointer(root map[string]any, pointer string) (any, error) { + if pointer == "#" { + return root, nil + } + if !strings.HasPrefix(pointer, "#/") { + return nil, fmt.Errorf("unsupported ref %q", pointer) + } + + var current any = root + for _, part := range strings.Split(strings.TrimPrefix(pointer, "#/"), "/") { + part = strings.ReplaceAll(strings.ReplaceAll(part, "~1", "/"), "~0", "~") + next, ok := current.(map[string]any) + if !ok { + return nil, fmt.Errorf("invalid ref %q", pointer) + } + current, ok = next[part] + if !ok { + return nil, fmt.Errorf("ref %q not found", pointer) + } + } + + return current, nil +} + +func cloneMap(input map[string]any) map[string]any { + cloned := make(map[string]any, len(input)) + for key, value := range input { + cloned[key] = cloneValue(value) + } + return cloned +} + +func cloneValue(value any) any { + switch typed := value.(type) { + case map[string]any: + return cloneMap(typed) + case []any: + cloned := make([]any, 0, len(typed)) + for _, item := range typed { + cloned = append(cloned, cloneValue(item)) + } + return cloned + default: + return value + } +} + +func goModReplaceTarget(goModPath, modulePath string) (string, error) { + data, err := os.ReadFile(goModPath) + if err != nil { + return "", err + } + + for _, line := range strings.Split(string(data), "\n") { + line = strings.TrimSpace(line) + if !strings.HasPrefix(line, "replace ") || !strings.Contains(line, modulePath) || !strings.Contains(line, "=>") { + continue + } + parts := strings.Fields(line) + if len(parts) < 4 { + continue + } + for i := 0; i < len(parts)-1; i++ { + if parts[i] == "=>" { + return parts[i+1], nil + } + } + } + + return "", fmt.Errorf("replace target for %s not found", modulePath) +} + +func isHTTPMethod(method string) bool { + switch strings.ToLower(method) { + case "get", "post", "put", "patch", "delete": + return true + default: + return false + } +} diff --git a/internal/commands/api/schema_test.go b/internal/commands/api/schema_test.go new file mode 100644 index 0000000..2b6d4e4 --- /dev/null +++ b/internal/commands/api/schema_test.go @@ -0,0 +1,193 @@ +package api + +import ( + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/tfcloud/internal/pkg/cmd" + "github.com/hashicorp/tfcloud/internal/pkg/iostreams" +) + +var testSchemaOperations = []schemaOperation{ + {OperationID: "cancelRun", Method: "POST", Path: "/runs/{run_id}/actions/cancel", Tags: []string{"runs"}, Summary: "Cancel a Run"}, + {OperationID: "forceCancelRun", Method: "POST", Path: "/runs/{run_id}/actions/force-cancel", Tags: []string{"runs"}, Summary: "Force cancel a Run"}, + {OperationID: "getRun", Method: "GET", Path: "/runs/{run_id}", Tags: []string{"runs"}, Summary: "Get Run details"}, + {OperationID: "getWorkspace", Method: "GET", Path: "/workspaces/{workspace_id}", Tags: []string{"workspaces"}, Summary: "Get Workspace"}, + {OperationID: "listWorkspaces", Method: "GET", Path: "/organizations/{organization_name}/workspaces", Tags: []string{"workspaces"}, Summary: "List Workspaces"}, + {OperationID: "createWorkspaceVar", Method: "POST", Path: "/workspaces/{workspace_id}/vars", Tags: []string{"vars"}, Summary: "Create a Variable"}, + {OperationID: "listWorkspaceVars", Method: "GET", Path: "/workspaces/{workspace_id}/vars", Tags: []string{"vars"}, Summary: "List Variables"}, +} + +func TestSchemaSearchFiltersToSameResource(t *testing.T) { + t.Parallel() + + results := filterSchemaResultsByResource(parseSchemaSearchIntent("workspace"), []schemaSearchResult{ + {Operation: schemaOperation{OperationID: "getWorkspace", Method: "GET", Path: "/workspaces/{workspace_id}", Tags: []string{"workspaces"}, Summary: "Get Workspace"}, Confidence: 0.9}, + {Operation: schemaOperation{OperationID: "cancelRun", Method: "POST", Path: "/runs/{run_id}/actions/cancel", Tags: []string{"runs"}, Summary: "Cancel Run"}, Confidence: 1.0}, + {Operation: schemaOperation{OperationID: "listWorkspaces", Method: "GET", Path: "/organizations/{organization_name}/workspaces", Tags: []string{"workspaces"}, Summary: "List Workspaces"}, Confidence: 0.8}, + }, 3) + got := resultIDs(results) + for _, operationID := range got { + if !strings.Contains(strings.ToLower(operationID), "workspace") { + t.Fatalf("expected workspace-related results, got %v", got) + } + } + if containsOperation(got, "listWorkspaceResources") { + t.Fatalf("expected root workspace query to exclude workspace resources, got %v", got) + } +} + +func TestCmdAPISchemaSearchRun(t *testing.T) { + t.Parallel() + r := require.New(t) + + io := iostreams.Test() + originalLoader := loadSchemaOperationsForSearch + originalSearcher := schemaOperationSearcher + loadSchemaOperationsForSearch = func() ([]schemaOperation, error) { + return testSchemaOperations, nil + } + schemaOperationSearcher = hybridSchemaSearcher{} + t.Cleanup(func() { + loadSchemaOperationsForSearch = originalLoader + schemaOperationSearcher = originalSearcher + }) + + command := newCmdAPISchemaSearch(testCommandContext(io)) + command.SetIO(io) + r.Equal(0, command.Run([]string{"cancel", "run"})) + + output := io.Output.String() + r.Contains(output, "operation-id") + r.Contains(output, "getRun") + r.Contains(output, "/runs/{run_id}") + r.Empty(io.Error.String()) +} + +func TestSchemaOperationDocumentDereferencesRefs(t *testing.T) { + t.Parallel() + + spec := map[string]any{ + "openapi": "3.0.0", + "paths": map[string]any{ + "/workspaces/{workspace_id}/vars": map[string]any{ + "post": map[string]any{ + "operationId": "createWorkspaceVar", + "summary": "Create a Variable", + "requestBody": map[string]any{ + "$ref": "#/components/requestBodies/CreateWorkspaceVar", + }, + "responses": map[string]any{ + "200": map[string]any{ + "content": map[string]any{ + "application/vnd.api+json": map[string]any{ + "schema": map[string]any{ + "$ref": "#/components/schemas/WorkspaceVarCreate", + }, + }, + }, + }, + }, + }, + }, + }, + "components": map[string]any{ + "requestBodies": map[string]any{ + "CreateWorkspaceVar": map[string]any{ + "required": true, + "content": map[string]any{ + "application/vnd.api+json": map[string]any{ + "schema": map[string]any{ + "$ref": "#/components/schemas/WorkspaceVarCreate", + }, + }, + }, + }, + }, + "schemas": map[string]any{ + "WorkspaceVarCreate": map[string]any{ + "type": "object", + "properties": map[string]any{ + "data": map[string]any{ + "type": "object", + }, + }, + }, + }, + }, + } + + doc, err := schemaOperationDocument(spec, "createWorkspaceVar") + if err != nil { + t.Fatal(err) + } + + paths := doc["paths"].(map[string]any) + pathItem := paths["/workspaces/{workspace_id}/vars"].(map[string]any) + post := pathItem["post"].(map[string]any) + requestBody := post["requestBody"].(map[string]any) + if requestBody["required"] != true { + t.Fatalf("expected dereferenced requestBody, got %#v", requestBody) + } + content := requestBody["content"].(map[string]any) + schema := content["application/vnd.api+json"].(map[string]any)["schema"].(map[string]any) + if schema["type"] != "object" { + t.Fatalf("expected dereferenced schema, got %#v", schema) + } + + responses := post["responses"].(map[string]any) + responseSchema := responses["200"].(map[string]any)["content"].(map[string]any)["application/vnd.api+json"].(map[string]any)["schema"].(map[string]any) + if responseSchema["$ref"] != "#/components/schemas/WorkspaceVarCreate" { + t.Fatalf("expected response schema ref to remain unresolved, got %#v", responseSchema) + } +} + +func TestCmdAPISchemaGetRun(t *testing.T) { + t.Parallel() + r := require.New(t) + + io := iostreams.Test() + originalLoader := loadSchemaDocumentForGet + loadSchemaDocumentForGet = func() (map[string]any, error) { + return map[string]any{ + "openapi": "3.0.0", + "paths": map[string]any{ + "/workspaces/{workspace_id}": map[string]any{ + "get": map[string]any{ + "operationId": "getWorkspace", + "summary": "Get Workspace", + }, + }, + }, + }, nil + } + t.Cleanup(func() { + loadSchemaDocumentForGet = originalLoader + }) + + command := newCmdAPISchemaGet(testCommandContext(io)) + command.SetIO(io) + r.Equal(0, command.Run([]string{"getWorkspace"})) + + output := io.Output.String() + r.Contains(output, `"operationId": "getWorkspace"`) + r.Contains(output, `"/workspaces/{workspace_id}"`) + r.Empty(io.Error.String()) +} + +func testCommandContext(io *iostreams.Testing) *cmd.Context { + return &cmd.Context{ + IO: io, + } +} + +func containsOperation(operations []string, want string) bool { + for _, operation := range operations { + if operation == want { + return true + } + } + return false +} From 83b397f3de8f62b815f01a4d2f6b485fab893c09 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Fri, 10 Apr 2026 14:18:58 -0400 Subject: [PATCH 02/14] Update api_schema_eval_test.go --- internal/commands/api/schema_eval_test.go | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/internal/commands/api/schema_eval_test.go b/internal/commands/api/schema_eval_test.go index 2068e26..2d80091 100644 --- a/internal/commands/api/schema_eval_test.go +++ b/internal/commands/api/schema_eval_test.go @@ -118,6 +118,44 @@ func TestSchemaSearchSummary(t *testing.T) { t.Log("\n" + strings.Join(rows, "\n")) } +func TestSpecBackedSchemaSearch(t *testing.T) { + operations, err := loadSchemaOperationsForSearch() + if err != nil { + t.Fatal(err) + } + + fixtures := []struct { + name string + query string + wantTop []string + }{ + {name: "workspace", query: "workspace", wantTop: []string{"getWorkspace", "listWorkspaces"}}, + {name: "organization", query: "organization", wantTop: []string{"getOrganization", "listOrganizations"}}, + {name: "variable", query: "variable", wantTop: []string{"createWorkspaceVar", "listWorkspaceVars"}}, + {name: "apply run", query: "apply run", wantTop: []string{"applyRun"}}, + } + + for _, fixture := range fixtures { + fixture := fixture + t.Run(fixture.name, func(t *testing.T) { + results, err := schemaOperationSearcher.Search(fixture.query, operations, maxSchemaSearchResults) + if err != nil { + t.Fatal(err) + } + if len(results) == 0 { + t.Fatal("got no results") + } + + got := resultIDs(results) + for _, want := range fixture.wantTop { + if !containsOperation(got, want) { + t.Fatalf("expected %q in spec-backed results, got %v", want, got) + } + } + }) + } +} + func resultIDs(results []schemaSearchResult) []string { ids := make([]string, 0, len(results)) for _, result := range results { From dcc9fa905662c6352ba3074438051e3509951956 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:42:03 -0400 Subject: [PATCH 03/14] Delete pull_request_template.md --- .github/pull_request_template.md | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md deleted file mode 100644 index fb2546b..0000000 --- a/.github/pull_request_template.md +++ /dev/null @@ -1,13 +0,0 @@ -## PCI review checklist - - - -- [ ] I have documented a clear reason for, and description of, the change I am making. - -- [ ] If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request. - -- [ ] If applicable, I've documented the impact of any changes to security controls. - - Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc. - -If you have any questions, please contact your direct supervisor, GRC (#team-grc), or the PCI working group (#proj-pci-reboot). You can also find more information at [PCI Compliance](https://hashicorp.atlassian.net/wiki/spaces/SEC/pages/2784559202/PCI+Compliance). From e315c8b5ddd16f1ba7326affc103c98c818f2a24 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:48:41 -0400 Subject: [PATCH 04/14] return clear message if no results --- internal/commands/api/schema.go | 12 +++++++++++- internal/commands/api/schema_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/internal/commands/api/schema.go b/internal/commands/api/schema.go index 31f4b8a..257c960 100644 --- a/internal/commands/api/schema.go +++ b/internal/commands/api/schema.go @@ -65,15 +65,20 @@ func newCmdAPISchemaSearch(ctx *cmd.Context) *cmd.Command { Command: "$ tfcloud api schema search workspace", }}, RunF: func(_ *cmd.Command, args []string) error { + query := joinSchemaQuery(args) operations, err := loadSchemaOperationsForSearch() if err != nil { return err } - results, err := schemaOperationSearcher.Search(joinSchemaQuery(args), operations, maxSchemaSearchResults) + results, err := schemaOperationSearcher.Search(query, operations, maxSchemaSearchResults) if err != nil { return err } + if len(results) == 0 { + writeSchemaNoResults(ctx, query) + return nil + } body, err := schemaSearchJSONAPIResponse(results) if err != nil { @@ -145,3 +150,8 @@ func joinSchemaQuery(args []string) string { } return query } + +func writeSchemaNoResults(ctx *cmd.Context, query string) { + cs := ctx.IO.ColorScheme() + _, _ = fmt.Fprintf(ctx.IO.Out(), "%s No API operations matched %q.\n", cs.WarningLabel(), query) +} diff --git a/internal/commands/api/schema_test.go b/internal/commands/api/schema_test.go index 2b6d4e4..24f8aae 100644 --- a/internal/commands/api/schema_test.go +++ b/internal/commands/api/schema_test.go @@ -66,6 +66,31 @@ func TestCmdAPISchemaSearchRun(t *testing.T) { r.Empty(io.Error.String()) } +func TestCmdAPISchemaSearchRunNoResults(t *testing.T) { + t.Parallel() + r := require.New(t) + + io := iostreams.Test() + originalLoader := loadSchemaOperationsForSearch + originalSearcher := schemaOperationSearcher + loadSchemaOperationsForSearch = func() ([]schemaOperation, error) { + return testSchemaOperations, nil + } + schemaOperationSearcher = hybridSchemaSearcher{} + t.Cleanup(func() { + loadSchemaOperationsForSearch = originalLoader + schemaOperationSearcher = originalSearcher + }) + + command := newCmdAPISchemaSearch(testCommandContext(io)) + command.SetIO(io) + r.Equal(0, command.Run([]string{"wrokspaec"})) + + output := io.Output.String() + r.Contains(output, `No API operations matched "wrokspaec"`) + r.Empty(io.Error.String()) +} + func TestSchemaOperationDocumentDereferencesRefs(t *testing.T) { t.Parallel() From ff9c38c6ec0da7245b1f0f768d465d4d05a6a55d Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Fri, 10 Apr 2026 16:51:38 -0400 Subject: [PATCH 05/14] drop confidence and id cols from results table --- internal/commands/api/schema_search.go | 4 ---- internal/commands/api/schema_test.go | 1 - 2 files changed, 5 deletions(-) diff --git a/internal/commands/api/schema_search.go b/internal/commands/api/schema_search.go index 7e1683d..3be9b1e 100644 --- a/internal/commands/api/schema_search.go +++ b/internal/commands/api/schema_search.go @@ -2,7 +2,6 @@ package api import ( "encoding/json" - "fmt" "sort" "strings" ) @@ -95,14 +94,11 @@ func schemaSearchJSONAPIResponse(results []schemaSearchResult) ([]byte, error) { data := make([]map[string]any, 0, len(results)) for _, result := range results { data = append(data, map[string]any{ - "id": strings.ToLower(result.Operation.OperationID), - "type": "api-operations", "attributes": map[string]any{ "operation-id": result.Operation.OperationID, "method": result.Operation.Method, "path": result.Operation.Path, "summary": result.Operation.Summary, - "confidence": fmt.Sprintf("%.2f", result.Confidence), }, }) } diff --git a/internal/commands/api/schema_test.go b/internal/commands/api/schema_test.go index 24f8aae..b165574 100644 --- a/internal/commands/api/schema_test.go +++ b/internal/commands/api/schema_test.go @@ -60,7 +60,6 @@ func TestCmdAPISchemaSearchRun(t *testing.T) { r.Equal(0, command.Run([]string{"cancel", "run"})) output := io.Output.String() - r.Contains(output, "operation-id") r.Contains(output, "getRun") r.Contains(output, "/runs/{run_id}") r.Empty(io.Error.String()) From 6c386a3c973bf44577fdfae16bb095e5ad2b01b6 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Fri, 10 Apr 2026 17:05:06 -0400 Subject: [PATCH 06/14] inject get into no verb queries --- .../commands/api/schema_search_helpers.go | 4 ++++ internal/commands/api/schema_test.go | 19 +++---------------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/internal/commands/api/schema_search_helpers.go b/internal/commands/api/schema_search_helpers.go index 92ded16..6f99cc0 100644 --- a/internal/commands/api/schema_search_helpers.go +++ b/internal/commands/api/schema_search_helpers.go @@ -56,6 +56,10 @@ func parseSchemaSearchIntent(query string) schemaSearchIntent { resources = append(resources, token) } + if verb == "" && len(resources) > 0 { + verb = "get" + } + return schemaSearchIntent{ Tokens: tokens, Verb: verb, diff --git a/internal/commands/api/schema_test.go b/internal/commands/api/schema_test.go index b165574..7604ace 100644 --- a/internal/commands/api/schema_test.go +++ b/internal/commands/api/schema_test.go @@ -65,28 +65,15 @@ func TestCmdAPISchemaSearchRun(t *testing.T) { r.Empty(io.Error.String()) } -func TestCmdAPISchemaSearchRunNoResults(t *testing.T) { +func TestWriteSchemaNoResults(t *testing.T) { t.Parallel() r := require.New(t) io := iostreams.Test() - originalLoader := loadSchemaOperationsForSearch - originalSearcher := schemaOperationSearcher - loadSchemaOperationsForSearch = func() ([]schemaOperation, error) { - return testSchemaOperations, nil - } - schemaOperationSearcher = hybridSchemaSearcher{} - t.Cleanup(func() { - loadSchemaOperationsForSearch = originalLoader - schemaOperationSearcher = originalSearcher - }) - - command := newCmdAPISchemaSearch(testCommandContext(io)) - command.SetIO(io) - r.Equal(0, command.Run([]string{"wrokspaec"})) + writeSchemaNoResults(testCommandContext(io), "zzzznotrealresource") output := io.Output.String() - r.Contains(output, `No API operations matched "wrokspaec"`) + r.Contains(output, `No API operations matched "zzzznotrealresource"`) r.Empty(io.Error.String()) } From db4d9a1349f3da69d5f28d242a4490ccb72149a9 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:53:32 -0400 Subject: [PATCH 07/14] Update schema.go --- internal/commands/api/schema.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/internal/commands/api/schema.go b/internal/commands/api/schema.go index 257c960..6243866 100644 --- a/internal/commands/api/schema.go +++ b/internal/commands/api/schema.go @@ -3,6 +3,7 @@ package api import ( "encoding/json" "fmt" + "strings" "github.com/hashicorp/tfcloud/internal/pkg/cmd" "github.com/hashicorp/tfcloud/internal/pkg/heredoc" @@ -141,14 +142,7 @@ func newCmdAPISchemaGet(ctx *cmd.Context) *cmd.Command { } func joinSchemaQuery(args []string) string { - if len(args) == 0 { - return "" - } - query := args[0] - for i := 1; i < len(args); i++ { - query += " " + args[i] - } - return query + return strings.Join(args, " ") } func writeSchemaNoResults(ctx *cmd.Context, query string) { From 8ee2acecc2dfff28bbadfa31ff3fac030ebf2ec5 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:57:37 -0400 Subject: [PATCH 08/14] thread cancellation context into search --- internal/commands/api/schema.go | 12 ++++++++++-- internal/commands/api/schema_eval_test.go | 9 +++++---- internal/commands/api/schema_search.go | 5 +++-- internal/commands/api/schema_search_bluge.go | 7 +++++-- internal/commands/api/schema_test.go | 4 +++- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/internal/commands/api/schema.go b/internal/commands/api/schema.go index 6243866..9230a6b 100644 --- a/internal/commands/api/schema.go +++ b/internal/commands/api/schema.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "strings" @@ -19,7 +20,7 @@ type schemaOperation struct { } type schemaSearcher interface { - Search(query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) + Search(ctx context.Context, query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) } var ( @@ -72,7 +73,7 @@ func newCmdAPISchemaSearch(ctx *cmd.Context) *cmd.Command { return err } - results, err := schemaOperationSearcher.Search(query, operations, maxSchemaSearchResults) + results, err := schemaOperationSearcher.Search(schemaSearchContext(ctx), query, operations, maxSchemaSearchResults) if err != nil { return err } @@ -149,3 +150,10 @@ func writeSchemaNoResults(ctx *cmd.Context, query string) { cs := ctx.IO.ColorScheme() _, _ = fmt.Fprintf(ctx.IO.Out(), "%s No API operations matched %q.\n", cs.WarningLabel(), query) } + +func schemaSearchContext(ctx *cmd.Context) context.Context { + if ctx != nil && ctx.ShutdownCtx != nil { + return ctx.ShutdownCtx + } + return context.Background() +} diff --git a/internal/commands/api/schema_eval_test.go b/internal/commands/api/schema_eval_test.go index 2d80091..1281c94 100644 --- a/internal/commands/api/schema_eval_test.go +++ b/internal/commands/api/schema_eval_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "fmt" "strings" @@ -45,7 +46,7 @@ func TestRepresentativeSchemaQueriesStayWithinResource(t *testing.T) { t.Run(fixture.name, func(t *testing.T) { t.Parallel() - results, err := schemaOperationSearcher.Search(fixture.query, fixture.operations, 3) + results, err := schemaOperationSearcher.Search(context.Background(), fixture.query, fixture.operations, 3) if err != nil { t.Fatal(err) } @@ -77,7 +78,7 @@ func TestHybridSchemaSearcherLimitsAndShapesResults(t *testing.T) { }) } - results, err := schemaOperationSearcher.Search("workspace", operations, maxSchemaSearchResults) + results, err := schemaOperationSearcher.Search(context.Background(), "workspace", operations, maxSchemaSearchResults) if err != nil { t.Fatal(err) } @@ -108,7 +109,7 @@ func TestSchemaSearchSummary(t *testing.T) { rows = append(rows, fmt.Sprintf("%-18s %s", "query", "top results")) for _, fixture := range fixtures { - results, err := schemaOperationSearcher.Search(fixture.query, fixture.operations, maxSchemaSearchResults) + results, err := schemaOperationSearcher.Search(context.Background(), fixture.query, fixture.operations, maxSchemaSearchResults) if err != nil { t.Fatalf("query=%q error: %v", fixture.query, err) } @@ -138,7 +139,7 @@ func TestSpecBackedSchemaSearch(t *testing.T) { for _, fixture := range fixtures { fixture := fixture t.Run(fixture.name, func(t *testing.T) { - results, err := schemaOperationSearcher.Search(fixture.query, operations, maxSchemaSearchResults) + results, err := schemaOperationSearcher.Search(context.Background(), fixture.query, operations, maxSchemaSearchResults) if err != nil { t.Fatal(err) } diff --git a/internal/commands/api/schema_search.go b/internal/commands/api/schema_search.go index 3be9b1e..1571a77 100644 --- a/internal/commands/api/schema_search.go +++ b/internal/commands/api/schema_search.go @@ -1,6 +1,7 @@ package api import ( + "context" "encoding/json" "sort" "strings" @@ -16,7 +17,7 @@ type schemaSearchResult struct { type hybridSchemaSearcher struct{} -func (s hybridSchemaSearcher) Search(query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) { +func (s hybridSchemaSearcher) Search(ctx context.Context, query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) { candidateLimit := limit * 3 if candidateLimit < 10 { candidateLimit = 10 @@ -25,7 +26,7 @@ func (s hybridSchemaSearcher) Search(query string, operations []schemaOperation, candidateLimit = len(operations) } - results, err := blugeRetrieve(query, operations, candidateLimit) + results, err := blugeRetrieve(ctx, query, operations, candidateLimit) if err != nil { return nil, err } diff --git a/internal/commands/api/schema_search_bluge.go b/internal/commands/api/schema_search_bluge.go index 02b5757..c41b8b8 100644 --- a/internal/commands/api/schema_search_bluge.go +++ b/internal/commands/api/schema_search_bluge.go @@ -8,10 +8,13 @@ import ( "github.com/blugelabs/bluge" ) -func blugeRetrieve(query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) { +func blugeRetrieve(ctx context.Context, query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) { if limit <= 0 || limit > len(operations) { limit = len(operations) } + if ctx == nil { + ctx = context.Background() + } writer, err := bluge.OpenWriter(bluge.InMemoryOnlyConfig()) if err != nil { @@ -36,7 +39,7 @@ func blugeRetrieve(query string, operations []schemaOperation, limit int) ([]sch searchQuery := blugeQueryForIntent(parseSchemaSearchIntent(query)) request := bluge.NewTopNSearch(limit, searchQuery) - iterator, err := reader.Search(context.Background(), request) + iterator, err := reader.Search(ctx, request) if err != nil { return nil, err } diff --git a/internal/commands/api/schema_test.go b/internal/commands/api/schema_test.go index 7604ace..a5bccad 100644 --- a/internal/commands/api/schema_test.go +++ b/internal/commands/api/schema_test.go @@ -1,6 +1,7 @@ package api import ( + "context" "strings" "testing" @@ -190,7 +191,8 @@ func TestCmdAPISchemaGetRun(t *testing.T) { func testCommandContext(io *iostreams.Testing) *cmd.Context { return &cmd.Context{ - IO: io, + IO: io, + ShutdownCtx: context.Background(), } } From 896b5a42a9023733ec5fd4887ef3461717daa7a8 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:39:20 -0400 Subject: [PATCH 09/14] Implement Go embed for OpenAPI spec --- internal/commands/api/openapi/spec.json | 29748 ++++++++++++++++++++ internal/commands/api/schema.go | 13 +- internal/commands/api/schema_eval_test.go | 4 +- internal/commands/api/schema_spec.go | 130 +- internal/commands/api/schema_test.go | 20 +- 5 files changed, 29829 insertions(+), 86 deletions(-) create mode 100644 internal/commands/api/openapi/spec.json diff --git a/internal/commands/api/openapi/spec.json b/internal/commands/api/openapi/spec.json new file mode 100644 index 0000000..268f618 --- /dev/null +++ b/internal/commands/api/openapi/spec.json @@ -0,0 +1,29748 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "2.6.0", + "title": "HCP Terraform API v2-Beta", + "description": "OpenAPI Specification for the HCP Terraform API V2 Public Beta.", + "license": { + "name": "MPL-2.0", + "url": "https://www.mozilla.org/en-US/MPL/2.0/" + }, + "contact": { + "name": "API Support", + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs" + } + }, + "servers": [ + { + "url": "https://app.terraform.io/api/v2" + } + ], + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + { + "name": "accounts", + "x-displayName": "Accounts", + "description": "Account actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/account" + } + }, + { + "name": "agent-pools", + "x-displayName": "Agents and Agent Pools", + "description": "Agent and Agent Pool actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/agents" + } + }, + { + "name": "audit-trails", + "x-vis": [ + "hcpt" + ], + "x-displayName": "Audit Trails", + "description": "Audit trail event listing for HCP Terraform organizations", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/audit-trails" + } + }, + { + "name": "auditing", + "x-displayName": "Auditing", + "description": "Auditing actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/audit-trails" + } + }, + { + "name": "feature-sets", + "x-vis": [ + "hcpt" + ], + "x-displayName": "Feature Sets", + "description": "Feature set actions representing different pricing plans", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/feature-sets" + } + }, + { + "name": "subscriptions", + "x-vis": [ + "hcpt" + ], + "x-displayName": "Subscriptions", + "description": "Subscription actions for HCP Terraform billing and feature access", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/subscriptions" + } + }, + { + "name": "billing-invoices", + "x-vis": [ + "hcpt" + ], + "x-displayName": "Billing Invoices", + "description": "Billing invoice management for credit-card-billed HCP Terraform organizations", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/invoices" + } + }, + { + "name": "configuration-versions", + "x-displayName": "Configuration Versions", + "description": "Configuration Version actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/configuration-versions" + } + }, + { + "name": "organizations", + "x-displayName": "Organizations", + "description": "Organization actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/organizations" + } + }, + { + "name": "organization-memberships", + "x-displayName": "Organization Memberships", + "description": "Organization membership management, including inviting and removing members", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/organization-memberships" + } + }, + { + "name": "token-ttl-policies", + "x-displayName": "Token TTL Policies", + "description": "Token TTL policy management, including creating and updating policies" + }, + { + "name": "projects", + "x-displayName": "Projects", + "description": "Project actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/projects" + } + }, + { + "name": "workspaces", + "x-displayName": "Workspaces", + "description": "Workspace management, locking, and related operations", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/workspaces" + } + }, + { + "name": "varsets", + "x-displayName": "Variable Sets", + "description": "Variable set management for organizations, projects, and workspaces", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/variable-sets" + } + }, + { + "name": "registry", + "x-displayName": "Registry", + "description": "Private Registry actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/registry" + } + }, + { + "name": "runs", + "x-displayName": "Runs", + "description": "Run actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/run" + } + }, + { + "name": "run-tasks", + "x-displayName": "Run Tasks", + "description": "Run task actions for organizations and workspaces", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/run-tasks/run-tasks" + } + }, + { + "name": "task-stages", + "x-displayName": "Run Task Stages and Results", + "description": "Run task stage and result actions for tracking run task execution", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/run-tasks/run-task-stages" + } + }, + { + "name": "policies", + "x-displayName": "Policies", + "description": "Sentinel and OPA policy management for organizations", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/policies" + } + }, + { + "name": "policy-checks", + "x-displayName": "Policy Checks", + "description": "Sentinel policy check actions for runs", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/policy-checks" + } + }, + { + "name": "policy-set-params", + "x-displayName": "Policy Set Parameters", + "description": "Sentinel policy set parameter management", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/policy-set-params" + } + }, + { + "name": "policy-sets", + "x-displayName": "Policy Sets", + "description": "Policy set management including workspace, project, and policy associations", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/policy-sets" + } + }, + { + "name": "policy-set-versions", + "x-displayName": "Policy Set Versions", + "description": "Policy set version management and policy file uploads", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/policy-sets" + } + }, + { + "name": "policy-evaluations", + "x-displayName": "Policy Evaluations", + "description": "Sentinel and OPA policy evaluation actions for task stages and policy set outcomes", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/policy-evaluations" + } + }, + { + "name": "run-triggers", + "x-displayName": "Run Triggers", + "description": "Run trigger actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/run-triggers" + } + }, + { + "name": "notification-configurations", + "x-displayName": "Notification Configurations", + "description": "Notification configuration actions for workspaces and teams", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/notification-configurations" + } + }, + { + "name": "plans", + "x-displayName": "Plans", + "description": "Plan actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/plans" + } + }, + { + "name": "assessment-results", + "x-displayName": "Assessment Results", + "description": "Assessment Result actions" + }, + { + "name": "plan-exports", + "x-displayName": "Plan Exports", + "description": "Plan export actions for downloading exported plan data", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/plan-exports" + } + }, + { + "name": "applies", + "x-displayName": "Applies", + "description": "Applies", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/applies" + } + }, + { + "name": "cost-estimates", + "x-displayName": "Cost Estimates", + "description": "Cost estimate actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/cost-estimates" + } + }, + { + "name": "state-versions", + "x-displayName": "State Versions", + "description": "State version actions for reading, creating, and managing Terraform state versions for a workspace", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/state-versions" + } + }, + { + "name": "state-version-outputs", + "x-displayName": "State Version Outputs", + "description": "State version output actions for reading Terraform output values from a state version or a workspace's current state", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/state-version-outputs" + } + }, + { + "name": "authentication-tokens", + "x-displayName": "Authentication Tokens", + "description": "Authentication Token Actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/users-teams-organizations/api-tokens" + } + }, + { + "name": "users", + "x-displayName": "Users", + "description": "User actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/users" + } + }, + { + "name": "teams", + "x-displayName": "Teams", + "description": "Team management actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/teams" + } + }, + { + "name": "team-projects", + "x-displayName": "Team Project Access", + "description": "Team access management for projects", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/team-project-access" + } + }, + { + "name": "team-access", + "x-displayName": "Team Workspace Access", + "description": "Team access management for workspaces", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/team-access" + } + }, + { + "name": "vcs", + "x-displayName": "Version Control System", + "description": "Operations related to VCS repositories and files", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/vcs" + } + }, + { + "name": "oauth-clients", + "x-displayName": "OAuth Clients", + "description": "OAuth Client management for VCS provider connections", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/oauth-clients" + } + }, + { + "name": "oauth-tokens", + "x-displayName": "OAuth Tokens", + "description": "OAuth Token management for VCS provider connections", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/oauth-tokens" + } + }, + { + "name": "github-app-installations", + "x-displayName": "GitHub App Installations", + "description": "GitHub App installation management for connecting GitHub accounts and organizations", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/github-app-installations" + } + }, + { + "name": "vcs-events", + "x-displayName": "VCS Events", + "description": "VCS event listing and filtering for an organization", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/vcs-events" + } + }, + { + "name": "queries", + "x-displayName": "Queries", + "description": "Query actions", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/queries" + } + }, + { + "name": "ssh-keys", + "x-displayName": "SSH Keys", + "description": "SSH Key management", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/ssh-keys" + } + }, + { + "name": "change-requests", + "x-displayName": "Change Requests", + "description": "Change request actions for tracking workspace to-dos", + "externalDocs": { + "url": "https://developer.hashicorp.com/terraform/cloud-docs/api-docs/change-requests" + } + } + ], + "paths": { + "/account/details": { + "get": { + "operationId": "getAccountDetails", + "summary": "Account Details", + "description": "Get your account details", + "tags": [ + "accounts" + ], + "responses": { + "200": { + "description": "Account details", + "content": { + "application/vnd.api+json": { + "examples": { + "successResponse": { + "summary": "Example successful response", + "value": { + "data": { + "type": "users", + "id": "user-12345678" + } + } + } + }, + "schema": { + "description": "User resource representing the account details of the authenticated user.\nFor internal reasons, HCP Terraform associates team and organization tokens\nwith a synthetic user account called service user.\n", + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/user" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/account/update": { + "patch": { + "operationId": "updateAccount", + "summary": "Update account", + "description": "Update your username and email address", + "tags": [ + "accounts" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/account_update" + } + } + } + }, + "responses": { + "200": { + "description": "Account updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/user" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/account/password": { + "patch": { + "operationId": "updateAccountPassword", + "summary": "Update account password", + "description": "Change your account password", + "tags": [ + "accounts" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/account_password" + } + } + } + }, + "responses": { + "200": { + "description": "Account updated", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/user" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/account/hcp-organizations/{hcp_organization_id}": { + "x-vis": [ + "hcpt" + ], + "get": { + "operationId": "getHCPOrganization", + "summary": "HCP Organization", + "tags": [ + "accounts" + ], + "description": "Get details of a specific HCP organization", + "parameters": [ + { + "name": "hcp_organization_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Successful response", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/hcp-organization" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/hcp-billing-account" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/feature-sets": { + "x-vis": [ + "hcpt" + ], + "get": { + "summary": "List Feature Sets", + "description": "Lists the feature sets available in HCP Terraform. Returns feature sets that are active, current, and public.", + "operationId": "listFeatureSets", + "tags": [ + "feature-sets" + ], + "parameters": [ + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved feature sets", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/feature-set" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Not found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/feature-sets": { + "x-vis": [ + "hcpt" + ], + "get": { + "summary": "List Feature Sets for Organization", + "description": "Lists the feature sets a particular organization is eligible to access.", + "operationId": "listOrganizationFeatureSets", + "tags": [ + "feature-sets" + ], + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "description": "The name of the organization", + "schema": { + "type": "string" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved feature sets for the organization", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/feature-set" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "403": { + "description": "Forbidden", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization not found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/subscriptions/{id}": { + "x-vis": [ + "hcpt" + ], + "get": { + "operationId": "showSubscription", + "summary": "Show a subscription", + "description": "Show details of a subscription.", + "tags": [ + "subscriptions" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the subscription to show.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Subscription details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/subscription" + } + } + } + } + } + }, + "default": { + "description": "Subscription not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/invoices": { + "x-vis": [ + "hcpt" + ], + "get": { + "operationId": "listOrganizationInvoices", + "summary": "List organization invoices", + "description": "Lists the previous invoices for an organization. This endpoint uses cursor-based pagination with a fixed page size of 10 items. Pass the value of meta.continuation as the cursor parameter to retrieve the next page. When meta.continuation is null there are no further pages.", + "tags": [ + "billing-invoices" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "cursor", + "schema": { + "type": "string" + }, + "required": false, + "description": "The ID of the invoice where the page should start. If omitted, the endpoint returns the first page." + } + ], + "responses": { + "200": { + "description": "Invoice list", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/billing-invoice" + } + }, + "meta": { + "type": "object", + "properties": { + "continuation": { + "type": "string", + "nullable": true, + "description": "The cursor value to use for the next page request. Null when there are no more items." + } + } + } + } + } + } + } + }, + "default": { + "description": "Unauthorized, forbidden, or not found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/invoices/next": { + "x-vis": [ + "hcpt" + ], + "get": { + "operationId": "showOrganizationNextInvoice", + "summary": "Get next invoice", + "description": "Returns the upcoming invoice for the next billing period for an organization. Returns null when no upcoming invoice is available.", + "tags": [ + "billing-invoices" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "responses": { + "200": { + "description": "Upcoming invoice, or null if none is available", + "content": { + "application/json": { + "schema": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "$ref": "#/components/schemas/billing-invoice" + } + } + } + } + } + }, + "default": { + "description": "Unauthorized, forbidden, or not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/agent-pools": { + "post": { + "operationId": "createAgentPool", + "summary": "Create Agent Pool", + "description": "Create an agent pool for an organization.", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Name of the organization" + } + ], + "responses": { + "200": { + "description": "Agent pool created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/agent-pool" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "get": { + "operationId": "listAgentPools", + "summary": "List Agent Pools", + "description": "List agent pools, their agents, and their tokens for an organization.", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Name of the organization" + }, + { + "in": "query", + "name": "filter[allowed-workspaces][name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filters agent pools to those associated with the given workspace. The workspace must have permission to use the agent pool." + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. Agent pools are searchable by name." + }, + { + "in": "query", + "name": "sort", + "schema": { + "type": "string" + }, + "required": false, + "description": "Allows sorting the returned agents pools. Valid values are \"name\" and \"created-at\". Prepending a hyphen to the sort parameter will reverse the order (e.g. \"-name\")." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Agent pools", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/agent-pool" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/agent-pools/{agent_pool_id}": { + "get": { + "operationId": "getAgentPool", + "summary": "Get Agent Pool details", + "description": "Get details about an agent pool", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "agent_pool_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Agent Pool ID" + } + ], + "responses": { + "200": { + "description": "Agent pool details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/agent-pool" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateAgentPool", + "summary": "Update Agent Pool", + "description": "Update an agent pool", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "agent_pool_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Agent Pool ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/agent-pool" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Agent pool updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/agent-pool" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAgentPool", + "summary": "Delete Agent Pool", + "description": "Delete an agent pool", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "agent_pool_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Agent Pool ID" + } + ], + "responses": { + "204": { + "description": "Agent pool deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/agent-pools/{agent_pool_id}/agents": { + "get": { + "operationId": "listAgents", + "summary": "List Agents", + "description": "List all agents in the specified agent pool.", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "agent_pool_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the Agent Pool to list." + }, + { + "in": "query", + "name": "filter[last-ping-since]", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "description": "Accepts a date in ISO8601 format (ex. `2020-08-11T10:41:23Z`)." + }, + { + "in": "query", + "name": "sort", + "schema": { + "type": "string" + }, + "required": false, + "description": "Allows sorting the returned agents. Valid value is \"created-at\". Prepending a hyphen to the sort parameter will reverse the order (e.g. \"-name\")." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/agent" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Agent Pool not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/agents/{agent_id}": { + "get": { + "operationId": "getAgent", + "summary": "Get Agent details", + "description": "Get details about an agent", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "agent_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Agent ID" + } + ], + "responses": { + "200": { + "description": "Agent details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/agent" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAgent", + "summary": "Delete Agent", + "description": "Remove an agent", + "tags": [ + "agent-pools" + ], + "parameters": [ + { + "in": "path", + "name": "agent_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Agent ID" + } + ], + "responses": { + "204": { + "description": "Agent removed" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations": { + "get": { + "operationId": "listOrganizations", + "summary": "List Organizations", + "description": "List organizations.", + "tags": [ + "organizations" + ], + "parameters": [ + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "subscription" + ] + }, + "required": false, + "description": "Optionally side-load relationships of the specified name" + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. Organizations are searchable by name and notification email." + }, + { + "in": "query", + "name": "q[email]", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. This query searches organizations by notification email." + }, + { + "in": "query", + "name": "q[name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. This query searches organizations by name." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Organizations list", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/organization" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/subscription" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createOrganization", + "summary": "Create Organization", + "description": "Create an organization.", + "tags": [ + "organizations" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Organization created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}": { + "get": { + "operationId": "getOrganization", + "summary": "Get Organization details", + "description": "Get details about an organization.", + "tags": [ + "organizations" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization Name" + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "subscription" + ] + }, + "required": false, + "description": "Optionally side-load relationships of the specified name" + } + ], + "responses": { + "200": { + "description": "Organization details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/subscription" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "put": { + "tags": [ + "organizations" + ], + "operationId": "updateOrganization", + "summary": "Update Organization", + "description": "Update an organization.", + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization Name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Organization updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "tags": [ + "organizations" + ], + "operationId": "updateOrganization", + "summary": "Update Organization", + "description": "Update an organization.", + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization Name" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Organization updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOrganization", + "summary": "Delete Organization", + "description": "Delete an organization.", + "tags": [ + "organizations" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization Name" + } + ], + "responses": { + "204": { + "description": "Organization deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/organization-memberships": { + "get": { + "operationId": "listOrganizationMemberships", + "summary": "List Organization Memberships", + "description": "List all memberships in an organization. This includes both active members and invited users who have not yet accepted their invitation.", + "tags": [ + "organization-memberships" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization to list memberships for" + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. Memberships are searchable by user name or email (case-insensitive)." + }, + { + "in": "query", + "name": "filter[status]", + "schema": { + "type": "string", + "enum": [ + "active", + "invited" + ] + }, + "required": false, + "description": "Filter memberships by status. Can be \"active\" or \"invited\"." + }, + { + "in": "query", + "name": "filter[email]", + "schema": { + "type": "string", + "format": "email" + }, + "required": false, + "description": "Filter memberships by exact email address match." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "user", + "teams" + ] + }, + "required": false, + "description": "Optionally side-load relationships. Can include \"user\" or \"teams\"." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Organization memberships list", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/organization-membership" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/user" + }, + { + "$ref": "#/components/schemas/team" + }, + { + "$ref": "#/components/schemas/organization" + } + ] + } + } + } + } + } + } + }, + "400": { + "description": "Invalid filter or include parameter", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createOrganizationMembership", + "summary": "Invite a User to an Organization", + "description": "Invite a user to join an organization. Users can be invited by email address.", + "tags": [ + "organization-memberships" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization the user will be invited to join" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "organization-memberships" + ] + }, + "attributes": { + "type": "object", + "required": [ + "email" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "description": "The email address of the user to be invited" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "teams": { + "type": "object", + "required": [ + "data" + ], + "description": "A list of teams the invited user will be a member of. All users must be added to at least one team.", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string", + "description": "The team ID" + }, + "type": { + "type": "string", + "enum": [ + "teams" + ] + } + } + } + } + } + } + } + } + } + } + } + }, + "examples": { + "inviteUser": { + "summary": "Invite a user to an organization with team memberships", + "value": { + "data": { + "type": "organization-memberships", + "attributes": { + "email": "user@example.com" + }, + "relationships": { + "teams": { + "data": [ + { + "type": "teams", + "id": "team-GeLZkdnK6xAVjA5H" + }, + { + "type": "teams", + "id": "team-XxEoUFzP9pW3r5d1" + } + ] + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Successfully invited the user", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization-membership" + } + } + } + } + } + }, + "400": { + "description": "Unable to invite user due to organization limits", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Unable to invite user due to validation errors (e.g., invalid email, missing teams)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organization-memberships": { + "get": { + "operationId": "listUserOrganizationMemberships", + "summary": "List User's Own Organization Memberships", + "description": "List all organization memberships for the currently authenticated user.", + "tags": [ + "organization-memberships" + ], + "parameters": [ + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "user", + "teams", + "organization" + ] + }, + "required": false, + "description": "Optionally side-load relationships. Can include \"user\", \"teams\", or \"organization\"." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "User's organization memberships list", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/organization-membership" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/user" + }, + { + "$ref": "#/components/schemas/team" + }, + { + "$ref": "#/components/schemas/organization" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organization-memberships/{organization_membership_id}": { + "get": { + "operationId": "getOrganizationMembership", + "summary": "Show Organization Membership", + "description": "Get details about a specific organization membership.", + "tags": [ + "organization-memberships" + ], + "parameters": [ + { + "in": "path", + "name": "organization_membership_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The organization membership ID" + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "user", + "teams" + ] + }, + "required": false, + "description": "Optionally side-load relationships. Can include \"user\" or \"teams\"." + } + ], + "responses": { + "200": { + "description": "Organization membership details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/organization-membership" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/user" + }, + { + "$ref": "#/components/schemas/team" + } + ] + } + } + } + } + } + } + }, + "404": { + "description": "Organization membership not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOrganizationMembership", + "summary": "Remove User from Organization", + "description": "Remove a user from an organization. You cannot remove yourself from organizations which you own.", + "tags": [ + "organization-memberships" + ], + "parameters": [ + { + "in": "path", + "name": "organization_membership_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The organization membership ID" + } + ], + "responses": { + "204": { + "description": "Successfully removed the user from the organization" + }, + "403": { + "description": "Unable to remove the user. You cannot remove yourself from organizations which you own.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization membership not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/projects": { + "get": { + "operationId": "listProjects", + "summary": "List Projects", + "description": "List all projects in an organization.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "filter[names]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Comma-separated list of project names to filter by." + }, + { + "in": "query", + "name": "filter[permissions][create-workspace]", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "If present, returns a list of projects that the authenticated user can create workspaces in." + }, + { + "in": "query", + "name": "filter[permissions][update]", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "If present, returns a list of projects that the authenticated user can update." + }, + { + "in": "query", + "name": "sort", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optional. Allows sorting the organization's projects by \"name\". Prepending a hyphen to the sort parameter reverses the order. For example, \"-name\" sorts by name in reverse alphabetical order. If omitted, the default sort order is arbitrary but stable.\n" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of projects", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/project" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createProject", + "summary": "Create a Project", + "description": "Create a new project in an organization.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Project created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/project" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/token-ttl-policies": { + "get": { + "operationId": "listTokenTtlPolicies", + "summary": "List Token TTL Policies", + "description": "List all token TTL policies for an organization.", + "tags": [ + "token-ttl-policies" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization to list token TTL policies for" + } + ], + "responses": { + "200": { + "description": "Token TTL policies list", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/token-ttl-policy" + } + } + } + } + } + } + }, + "403": { + "description": "User is not part of the owners team of the organization", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization does not exist or user does not belong to the organization", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "put": { + "operationId": "upsertTokenTtlPolicies", + "summary": "Create or Update Token TTL Policies", + "description": "Create or Update token TTL policies for an organization.", + "tags": [ + "organization-token-ttl-policies" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "token_ttl_policies" + ], + "properties": { + "token_ttl_policies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/token-ttl-policy" + } + } + } + }, + "examples": { + "upsert": { + "summary": "Upsert token TTL policies", + "value": { + "token_ttl_policies": [ + { + "token-type": "ORG_TOKEN", + "max-ttl-ms": 3600000 + }, + { + "token-type": "USER_TOKEN", + "max-ttl-ms": 7200000 + } + ] + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Successfully created or updated token TTL policies", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/token-ttl-policy" + } + } + } + } + } + }, + "403": { + "description": "User is not part of the owners team of the organization", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization does not exist or user does not belong to the organization", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Unable to create token TTL policy due to validation errors", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/projects/{project_id}": { + "get": { + "operationId": "getProject", + "summary": "Get Project", + "description": "Get details of a specific project.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + } + ], + "responses": { + "200": { + "description": "Project details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/project" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateProject", + "summary": "Update Project", + "description": "Update an existing project.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Project updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/project" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteProject", + "summary": "Delete Project", + "description": "Delete a project.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + } + ], + "responses": { + "204": { + "description": "Project deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/projects/{project_id}/relationships/workspaces": { + "post": { + "operationId": "moveWorkspacesIntoProject", + "summary": "Move Workspaces into a Project", + "description": "Move one or more workspaces into a project. You must have permission to move workspaces on the destination project as well as any source project(s). If you are not authorized to move any of the workspaces in the request, or if any workspaces in the request are not found, then no workspaces will be moved.\n", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the destination project." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Successfully moved workspace(s)." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/projects/{project_id}/relationships/tag-bindings": { + "get": { + "operationId": "listProjectTagBindings", + "summary": "List Project Tag Bindings", + "description": "List all tags associated with a project.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + } + ], + "responses": { + "200": { + "description": "List of tags", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/tag-bindings-request" + } + } + } + }, + "404": { + "description": "Project not found or user unauthorized to view project", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addProjectTagBindings", + "summary": "Add Tag Bindings to a Project", + "description": "Add one or more tag bindings to a project.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/tag-bindings-request" + } + } + } + }, + "responses": { + "204": { + "description": "Tags added" + }, + "404": { + "description": "Project not found or user unauthorized to manage tags", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "replaceProjectTagBindings", + "summary": "Replace Tag Bindings in a Project", + "description": "Replace all tag bindings in a project.", + "tags": [ + "projects" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/tag-bindings-request" + } + } + } + }, + "responses": { + "204": { + "description": "Tag bindings replaced" + }, + "404": { + "description": "Project not found or user unauthorized to manage tag bindings", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/workspaces": { + "get": { + "operationId": "listWorkspaces", + "summary": "List Workspaces", + "description": "List all workspaces in an organization.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "search[name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Partial name to filter workspaces by name." + }, + { + "in": "query", + "name": "search[wildcard-name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Wildcard name filter for workspaces." + }, + { + "in": "query", + "name": "filter[current-run][status]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Comma-separated list of run statuses to filter workspaces by." + }, + { + "in": "query", + "name": "filter[project][id]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter workspaces by project external ID." + }, + { + "in": "query", + "name": "filter[tagged]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter workspaces by tag names." + }, + { + "in": "query", + "name": "filter[tagged][value]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter workspaces by tag key=value pairs." + }, + { + "in": "query", + "name": "sort", + "schema": { + "type": "string" + }, + "required": false, + "description": "Sort workspaces. Valid values include name, current-run.created-at. Prefix with a hyphen (e.g., -name) to sort in descending order.\n" + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Comma-separated list of relationship names to side-load (e.g., current_run, readme, effective_tag_bindings).\n" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of workspaces", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + }, + "status-counts": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "included": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "404": { + "description": "Organization not found or user unauthorized to view workspaces", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createWorkspace", + "summary": "Create a Workspace", + "description": "Create a new workspace in an organization.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "auto-apply": { + "type": "boolean" + }, + "auto-apply-run-trigger": { + "type": "boolean" + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + }, + "allow-destroy-plan": { + "type": "boolean" + }, + "file-triggers-enabled": { + "type": "boolean" + }, + "trigger-prefixes": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "trigger-patterns": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "queue-all-runs": { + "type": "boolean" + }, + "speculative-enabled": { + "type": "boolean" + }, + "structured-run-output-enabled": { + "type": "boolean" + }, + "assessments-enabled": { + "type": "boolean" + }, + "terraform-version": { + "type": "string" + }, + "working-directory": { + "type": "string", + "nullable": true + }, + "execution-mode": { + "type": "string", + "enum": [ + "remote", + "local", + "agent" + ] + }, + "operations": { + "type": "boolean", + "description": "Deprecated. Use execution-mode instead." + }, + "global-remote-state": { + "type": "boolean" + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "identifier": { + "type": "string" + }, + "branch": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "github-app-installation-id": { + "type": "string", + "nullable": true + }, + "tags-regex": { + "type": "string", + "nullable": true + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "project": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + }, + "agent-pool": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "agent-pools" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Workspace created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Organization not found or user unauthorized to create workspaces", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body or validation error", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/workspaces/{workspace_name}": { + "get": { + "operationId": "getWorkspaceByName", + "summary": "Get a Workspace by Name", + "description": "Get details of a workspace by organization name and workspace name.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "path", + "name": "workspace_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the workspace." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optionally side-load relationships. Comma-separated list of relationship names (e.g. current_run, current_state_version, locked_by, outputs, project, agent_pool).\n" + } + ], + "responses": { + "200": { + "description": "Workspace details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + }, + "included": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateWorkspaceByName", + "summary": "Update a Workspace by Name", + "description": "Update settings of an existing workspace by organization name and workspace name.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "path", + "name": "workspace_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "auto-apply": { + "type": "boolean" + }, + "auto-apply-run-trigger": { + "type": "boolean" + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + }, + "auto-destroy-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "allow-destroy-plan": { + "type": "boolean" + }, + "file-triggers-enabled": { + "type": "boolean" + }, + "trigger-prefixes": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "trigger-patterns": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "queue-all-runs": { + "type": "boolean" + }, + "speculative-enabled": { + "type": "boolean" + }, + "structured-run-output-enabled": { + "type": "boolean" + }, + "assessments-enabled": { + "type": "boolean" + }, + "terraform-version": { + "type": "string" + }, + "working-directory": { + "type": "string", + "nullable": true + }, + "execution-mode": { + "type": "string", + "enum": [ + "remote", + "local", + "agent" + ] + }, + "operations": { + "type": "boolean", + "description": "Deprecated. Use execution-mode instead." + }, + "global-remote-state": { + "type": "boolean" + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "identifier": { + "type": "string" + }, + "branch": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "github-app-installation-id": { + "type": "string", + "nullable": true + }, + "tags-regex": { + "type": "string", + "nullable": true + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "project": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + }, + "agent-pool": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "agent-pools" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Workspace updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteWorkspaceByName", + "summary": "Delete a Workspace by Name", + "description": "Delete a workspace by organization name and workspace name. This permanently removes the workspace and all its associated data.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "path", + "name": "workspace_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the workspace." + } + ], + "responses": { + "204": { + "description": "Workspace deleted" + }, + "404": { + "description": "Workspace not found or user unauthorized to delete workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/workspaces/{workspace_name}/actions/safe-delete": { + "post": { + "operationId": "safeDeleteWorkspaceByName", + "summary": "Safe Delete a Workspace by Name", + "description": "Delete a workspace by organization name and workspace name only if it has no resources under management. Returns a conflict error if the workspace has managed resources or is locked.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "path", + "name": "workspace_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the workspace." + } + ], + "responses": { + "204": { + "description": "Workspace deleted" + }, + "404": { + "description": "Workspace not found or user unauthorized to delete workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "409": { + "description": "Workspace has managed resources or is locked and cannot be safely deleted", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/projects/{project_id}/notification-configurations": { + "get": { + "summary": "List Notification Configurations for a Project", + "description": "List all notification configurations for a given project.\n", + "operationId": "listProjectNotificationConfigurations", + "tags": [ + "Notification Configurations" + ], + "parameters": [ + { + "name": "project_id", + "in": "path", + "description": "The ID of the project", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + } + }, + "404": { + "description": "Project not found" + } + } + }, + "post": { + "summary": "Create a Notification Configuration for a Project", + "description": "Create a new notification configuration for a given project.\n", + "operationId": "createProjectNotificationConfiguration", + "tags": [ + "Notification Configurations" + ], + "parameters": [ + { + "name": "project_id", + "in": "path", + "description": "The ID of the project", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Notification configuration created successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "404": { + "description": "Project not found" + }, + "422": { + "description": "Validation error" + } + } + } + }, + "/workspaces/{workspace_id}/notification-configurations": { + "get": { + "operationId": "listWorkspaceNotificationConfigurations", + "summary": "List Notification Configurations for a Workspace", + "description": "List all notification configurations for a workspace.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of notification configurations", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/notification-configuration" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createWorkspaceNotificationConfiguration", + "summary": "Create a Notification Configuration for a Workspace", + "description": "Create a new notification configuration for a workspace.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Notification configuration created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/teams/{team_id}/notification-configurations": { + "get": { + "operationId": "listTeamNotificationConfigurations", + "summary": "List Notification Configurations for a Team", + "description": "List all notification configurations for a team.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of notification configurations", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/notification-configuration" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createTeamNotificationConfiguration", + "summary": "Create a Notification Configuration for a Team", + "description": "Create a new notification configuration for a team.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Notification configuration created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/notification-configurations/{notification_configuration_id}": { + "get": { + "operationId": "getNotificationConfiguration", + "summary": "Show a Notification Configuration", + "description": "Get details about a notification configuration.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "notification_configuration_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the notification configuration." + } + ], + "responses": { + "200": { + "description": "Notification configuration details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateNotificationConfiguration", + "summary": "Update a Notification Configuration", + "description": "Update an existing notification configuration.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "notification_configuration_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the notification configuration." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Notification configuration updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteNotificationConfiguration", + "summary": "Delete a Notification Configuration", + "description": "Delete a notification configuration.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "notification_configuration_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the notification configuration." + } + ], + "responses": { + "204": { + "description": "Notification configuration deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/notification-configurations/{notification_configuration_id}/actions/enable": { + "post": { + "operationId": "enableNotificationConfiguration", + "summary": "Enable a Notification Configuration", + "description": "Enable a notification configuration by triggering a verification request.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "notification_configuration_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the notification configuration." + } + ], + "responses": { + "200": { + "description": "Notification configuration enabled", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/notification-configurations/{notification_configuration_id}/actions/verify": { + "post": { + "operationId": "verifyNotificationConfiguration", + "summary": "Verify a Notification Configuration", + "description": "Send a verification request to the configured destination URL.", + "tags": [ + "notification-configurations" + ], + "parameters": [ + { + "in": "path", + "name": "notification_configuration_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the notification configuration." + } + ], + "responses": { + "200": { + "description": "Notification configuration verified", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/notification-configuration" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/queries": { + "x-vs": [ + "internal-beta" + ], + "get": { + "operationId": "getWorkspaceQueries", + "summary": "Get Queries for a Workspace", + "description": "Get list of queries for a particular workspace.", + "tags": [ + "queries" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The id of the workspace." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of Queries", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/query" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/all-vars": { + "get": { + "operationId": "listAllVars", + "summary": "List All Variables Accessible to a Workspace", + "description": "This API returns the list of all variables that are accessible to a workspace. This includes variables defined directly on the workspace as well as variables inherited from any variable sets attached to the workspace.", + "tags": [ + "vars" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "responses": { + "200": { + "description": "List of all variables accessible to a workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/vars": { + "get": { + "operationId": "listWorkspaceVars", + "summary": "List Variables", + "description": "List variables for a workspace.", + "tags": [ + "vars" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "responses": { + "200": { + "description": "List of variables for the workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace-var" + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createWorkspaceVar", + "summary": "Create a Variable", + "description": "Create a variable for a workspace.", + "tags": [ + "vars" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "required": [ + "key", + "category" + ], + "properties": { + "key": { + "type": "string", + "description": "The name of the variable." + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the variable." + }, + "description": { + "type": "string", + "nullable": true, + "description": "The description of the variable." + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ], + "description": "Whether this is a Terraform or environment variable." + }, + "hcl": { + "type": "boolean", + "description": "Whether to evaluate the value of the variable as a string of HCL code." + }, + "sensitive": { + "type": "boolean", + "description": "Whether the value is sensitive." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Variable created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/vars/{id}": { + "get": { + "operationId": "showWorkspaceVar", + "summary": "Show a Variable", + "description": "Show details of a variable in a workspace.", + "tags": [ + "vars" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable." + } + ], + "responses": { + "200": { + "description": "Variable details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateWorkspaceVar", + "summary": "Update a Variable", + "description": "Update attributes of an existing variable in a workspace.", + "tags": [ + "vars" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "id": { + "type": "string", + "description": "The ID of the variable to update." + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "The name of the variable." + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the variable." + }, + "description": { + "type": "string", + "nullable": true, + "description": "The description of the variable." + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ], + "description": "Whether this is a Terraform or environment variable." + }, + "hcl": { + "type": "boolean", + "description": "Whether to evaluate the value of the variable as a string of HCL code." + }, + "sensitive": { + "type": "boolean", + "description": "Whether the value is sensitive." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Variable updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteWorkspaceVar", + "summary": "Delete a Variable", + "description": "Delete a variable from a workspace.", + "tags": [ + "vars" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable." + } + ], + "responses": { + "204": { + "description": "Variable deleted successfully" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/varsets/{varset_id}": { + "get": { + "operationId": "showVarset", + "summary": "Show a Variable Set", + "description": "Fetch details about the specified variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "responses": { + "200": { + "description": "Variable set details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/varset" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateVarset", + "summary": "Update a Variable Set", + "description": "Update attributes of an existing variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "varsets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the variable set." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Text displayed in the UI to contextualize the variable set and its purpose." + }, + "global": { + "type": "boolean", + "description": "When true, HCP Terraform automatically applies the variable set to all current and future workspaces in the organization." + }, + "priority": { + "type": "boolean", + "description": "When true, the variables in the set override any other variable values with a more specific scope." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "stacks": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "stacks" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "vars": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ] + } + } + } + } + } + } + } + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "organizations", + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Variable set updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/varset" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "updateVarsetPost", + "summary": "Update a Variable Set (POST)", + "description": "Update attributes of an existing variable set using POST.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "varsets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the variable set." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Text displayed in the UI to contextualize the variable set and its purpose." + }, + "global": { + "type": "boolean", + "description": "When true, HCP Terraform automatically applies the variable set to all current and future workspaces in the organization." + }, + "priority": { + "type": "boolean", + "description": "When true, the variables in the set override any other variable values with a more specific scope." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "stacks": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "stacks" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "vars": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ] + } + } + } + } + } + } + } + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "organizations", + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Variable set updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/varset" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteVarset", + "summary": "Delete a Variable Set", + "description": "Delete an existing variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "responses": { + "204": { + "description": "Variable set deleted successfully" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/varsets": { + "get": { + "operationId": "listOrganizationVarsets", + "summary": "List Variable Sets for an Organization", + "description": "List all variable sets for an organization.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. You can search for a variable set using its name." + }, + { + "in": "query", + "name": "filter[global]", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "When true, returns only global variable sets. When false, returns only non-global variable sets." + }, + { + "in": "query", + "name": "scope", + "schema": { + "type": "string", + "enum": [ + "owned" + ] + }, + "required": false, + "description": "When set to \"owned\", returns only organization-owned variable sets." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of variable sets for the organization", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/varset" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createVarset", + "summary": "Create a Variable Set", + "description": "Create a new variable set in an organization.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "varsets" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the variable set." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Text displayed in the UI to contextualize the variable set and its purpose." + }, + "global": { + "type": "boolean", + "description": "When true, HCP Terraform automatically applies the variable set to all current and future workspaces in the organization." + }, + "priority": { + "type": "boolean", + "description": "When true, the variables in the set override any other variable values with a more specific scope." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "stacks": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "stacks" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + }, + "vars": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ] + } + } + } + } + } + } + } + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "organizations", + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Variable set created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/varset" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/varsets/{varset_id}/relationships/vars": { + "get": { + "operationId": "listVarsetVars", + "summary": "List Variables in a Variable Set", + "description": "List all variables in a variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "responses": { + "200": { + "description": "List of variables in the variable set", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/var" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addVarsetVar", + "summary": "Add a Variable to a Variable Set", + "description": "Add a new variable to an existing variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "required": [ + "key", + "category" + ], + "properties": { + "key": { + "type": "string", + "description": "The name of the variable." + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the variable." + }, + "description": { + "type": "string", + "nullable": true, + "description": "The description of the variable." + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ], + "description": "Whether this is a Terraform or environment variable." + }, + "hcl": { + "type": "boolean", + "description": "Whether to evaluate the value of the variable as a string of HCL code." + }, + "sensitive": { + "type": "boolean", + "description": "Whether the value is sensitive. If true, variable is not visible in the UI." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Variable added to variable set", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/varsets/{varset_id}/relationships/vars/{id}": { + "get": { + "operationId": "showVarsetVar", + "summary": "Show a Variable in a Variable Set", + "description": "Show details of a variable in a variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable." + } + ], + "responses": { + "200": { + "description": "Variable details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateVarsetVar", + "summary": "Update a Variable in a Variable Set", + "description": "Update attributes of an existing variable in a variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable to update." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "The name of the variable." + }, + "value": { + "type": "string", + "nullable": true, + "description": "The value of the variable." + }, + "description": { + "type": "string", + "nullable": true, + "description": "The description of the variable." + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ], + "description": "Whether this is a Terraform or environment variable." + }, + "hcl": { + "type": "boolean", + "description": "Whether to evaluate the value of the variable as a string of HCL code." + }, + "sensitive": { + "type": "boolean", + "description": "Whether the value is sensitive." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Variable updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteVarsetVar", + "summary": "Delete a Variable from a Variable Set", + "description": "Delete a variable from a variable set.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable to delete." + } + ], + "responses": { + "204": { + "description": "Variable deleted successfully" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/varsets/{varset_id}/relationships/vars/{id}": { + "get": { + "operationId": "showWorkspaceVarsetVar", + "summary": "Show a Variable in a Variable Set (Workspace Context)", + "description": "Show details of a variable in a variable set, with overwrite context from the specified workspace.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace providing overwrite context." + }, + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable." + } + ], + "responses": { + "200": { + "description": "Variable details with workspace overwrite context", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/varsets/{varset_id}/relationships/vars": { + "get": { + "operationId": "listWorkspaceVarsetVars", + "summary": "List Variables in a Variable Set (Workspace Context)", + "description": "List all variables in a variable set, with overwrite context from the specified workspace.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace providing overwrite context." + }, + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "responses": { + "200": { + "description": "List of variables in the variable set with workspace overwrite context", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/var" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/varsets/{varset_id}/relationships/projects": { + "post": { + "operationId": "applyVarsetToProjects", + "summary": "Apply Variable Set to Projects", + "description": "Apply a variable set to one or more projects. When you apply a variable set to a project, all the workspaces in that project will have the variable set applied to them.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string", + "description": "The ID of the project to add the variable set to." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variable set successfully applied to the requested projects." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeVarsetFromProjects", + "summary": "Remove Variable Set from Projects", + "description": "Remove a variable set from one or more projects.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string", + "description": "The ID of the project to remove the variable set from." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variable set successfully removed from the requested projects." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/varsets/{varset_id}/relationships/workspaces": { + "post": { + "operationId": "applyVarsetToWorkspaces", + "summary": "Apply Variable Set to Workspaces", + "description": "Apply a variable set to one or more workspaces.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string", + "description": "The ID of the workspace to add the variable set to." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variable set successfully applied to the requested workspaces." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeVarsetFromWorkspaces", + "summary": "Remove Variable Set from Workspaces", + "description": "Remove a variable set from one or more workspaces.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string", + "description": "The ID of the workspace to remove the variable set from." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variable set successfully removed from the requested workspaces." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/varsets/{varset_id}/relationships/stacks": { + "post": { + "operationId": "applyVarsetToStacks", + "summary": "Apply Variable Set to Stacks", + "description": "Apply a variable set to one or more Stacks. Only available in HCP Terraform.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "stacks" + ] + }, + "id": { + "type": "string", + "description": "The ID of the Stack to add the variable set to." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variable set successfully applied to the requested Stacks." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeVarsetFromStacks", + "summary": "Remove Variable Set from Stacks", + "description": "Remove a variable set from one or more Stacks.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "varset_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the variable set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "stacks" + ] + }, + "id": { + "type": "string", + "description": "The ID of the Stack to remove the variable set from." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variable set successfully removed from the requested Stacks." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/projects/{project_id}/varsets": { + "get": { + "operationId": "listProjectVarsets", + "summary": "List Variable Sets for a Project", + "description": "List all variable sets for a project. This includes global variable sets from the project's organization.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the project." + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. You can search for a variable set using its name." + }, + { + "in": "query", + "name": "scope", + "schema": { + "type": "string", + "enum": [ + "applied", + "shared", + "owned", + "all" + ] + }, + "required": false, + "description": "Filter variable sets by scope relative to the project." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of variable sets for the project", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/varset" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/varsets": { + "get": { + "operationId": "listWorkspaceVarsets", + "summary": "List Variable Sets for a Workspace", + "description": "List all variable sets for a workspace. This includes global variable sets from the workspace's organization and variable sets attached to the project this workspace is contained within.", + "tags": [ + "varsets" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. You can search for a variable set using its name." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of variable sets for the workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/varset" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/resources": { + "get": { + "operationId": "listWorkspaceResources", + "summary": "List Workspace Resources", + "description": "List all resources in a workspace's current state.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace to retrieve resources from." + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optional search query to filter resources by address pattern." + }, + { + "in": "query", + "name": "sort", + "schema": { + "type": "string", + "enum": [ + "name:asc", + "name:desc", + "nameIndex:asc", + "nameIndex:desc", + "provider:asc", + "provider:desc", + "providerType:asc", + "providerType:desc", + "module:asc", + "module:desc", + "updatedAt:asc", + "updatedAt:desc" + ] + }, + "required": false, + "description": "Optional sort parameter. Allows sorting workspace resources by name, nameIndex, provider, providerType, module, or updatedAt. Format is \"field:order\" where order is \"asc\" or \"desc\".\n" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of workspace resources", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace-resource" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}": { + "get": { + "operationId": "getWorkspace", + "summary": "Get a Workspace", + "description": "Get details of a specific workspace by its external ID.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optionally side-load relationships. Comma-separated list of relationship names (e.g. current_run, current_state_version, locked_by, outputs, project, agent_pool).\n" + } + ], + "responses": { + "200": { + "description": "Workspace details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + }, + "included": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateWorkspace", + "summary": "Update a Workspace", + "description": "Update settings of an existing workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "auto-apply": { + "type": "boolean" + }, + "auto-apply-run-trigger": { + "type": "boolean" + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + }, + "auto-destroy-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "allow-destroy-plan": { + "type": "boolean" + }, + "file-triggers-enabled": { + "type": "boolean" + }, + "trigger-prefixes": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "trigger-patterns": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "queue-all-runs": { + "type": "boolean" + }, + "speculative-enabled": { + "type": "boolean" + }, + "structured-run-output-enabled": { + "type": "boolean" + }, + "assessments-enabled": { + "type": "boolean" + }, + "terraform-version": { + "type": "string" + }, + "working-directory": { + "type": "string", + "nullable": true + }, + "execution-mode": { + "type": "string", + "enum": [ + "remote", + "local", + "agent" + ] + }, + "operations": { + "type": "boolean", + "description": "Deprecated. Use execution-mode instead." + }, + "global-remote-state": { + "type": "boolean" + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "identifier": { + "type": "string" + }, + "branch": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "github-app-installation-id": { + "type": "string", + "nullable": true + }, + "tags-regex": { + "type": "string", + "nullable": true + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "project": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + }, + "agent-pool": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "agent-pools" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Workspace updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteWorkspace", + "summary": "Delete a Workspace", + "description": "Delete a workspace. This permanently removes the workspace and all its associated data including runs, state versions, and configuration versions.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "204": { + "description": "Workspace deleted" + }, + "404": { + "description": "Workspace not found or user unauthorized to delete workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/actions/lock": { + "post": { + "operationId": "lockWorkspace", + "summary": "Lock a Workspace", + "description": "Lock a workspace. A workspace can only be locked by one entity at a time. Returns a conflict error if the workspace is already locked.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": false, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "reason": { + "type": "string", + "nullable": true, + "description": "An optional reason for locking the workspace." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Workspace locked successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to lock workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "409": { + "description": "Workspace is already locked", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/actions/unlock": { + "post": { + "operationId": "unlockWorkspace", + "summary": "Unlock a Workspace", + "description": "Unlock a workspace. Users can unlock a workspace if they locked it. Unlocking a workspace locked by another user requires force-unlock. Returns a conflict error if the workspace is not locked by the requesting user.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "200": { + "description": "Workspace unlocked successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to unlock workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "409": { + "description": "Workspace is locked by another user", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/actions/force-unlock": { + "post": { + "operationId": "forceUnlockWorkspace", + "summary": "Force Unlock a Workspace", + "description": "Forcibly unlock a workspace regardless of who locked it. This action requires elevated permissions and should be used with caution.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "200": { + "description": "Workspace force-unlocked successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to force-unlock workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/actions/safe-delete": { + "post": { + "operationId": "safeDeleteWorkspace", + "summary": "Safe Delete a Workspace", + "description": "Delete a workspace only if it has no resources under management. Returns a conflict error if the workspace has managed resources or is locked.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "204": { + "description": "Workspace deleted" + }, + "404": { + "description": "Workspace not found or user unauthorized to delete workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "409": { + "description": "Workspace has managed resources or is locked and cannot be safely deleted", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/actions/assess": { + "post": { + "operationId": "assessWorkspace", + "summary": "Trigger a Workspace Assessment", + "description": "Trigger a drift detection assessment for a workspace. The workspace must have assessments enabled and not have a pending assessment already running.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "200": { + "description": "Assessment triggered successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to manage assessments", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "409": { + "description": "Assessment cannot be triggered in the current workspace state", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/relationships/remote-state-consumers": { + "get": { + "operationId": "listWorkspaceRemoteStateConsumers", + "summary": "List Remote State Consumers", + "description": "List the workspaces that are allowed to access this workspace's state. When global-remote-state is enabled on the workspace, this lists all workspaces in the organization; otherwise, it lists only the explicitly allowed consumers.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + }, + { + "in": "query", + "name": "show_only_configured", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "When true, return only explicitly configured remote state consumers even if global-remote-state is enabled.\n" + } + ], + "responses": { + "200": { + "description": "List of workspaces that can consume this workspace's remote state", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addWorkspaceRemoteStateConsumers", + "summary": "Add Remote State Consumers", + "description": "Add workspaces to the list of allowed remote state consumers.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string", + "description": "The external ID of the workspace to add as a consumer." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Remote state consumers updated" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage remote state consumers", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "replaceWorkspaceRemoteStateConsumers", + "summary": "Replace Remote State Consumers", + "description": "Replace the entire list of allowed remote state consumers with the provided list.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string", + "description": "The external ID of the workspace consumer." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Remote state consumers replaced" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage remote state consumers", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeWorkspaceRemoteStateConsumers", + "summary": "Remove Remote State Consumers", + "description": "Remove workspaces from the list of allowed remote state consumers.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string", + "description": "The external ID of the workspace consumer to remove." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Remote state consumers removed" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage remote state consumers", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/relationships/ssh-key": { + "patch": { + "operationId": "assignWorkspaceSshKey", + "summary": "Assign an SSH Key to a Workspace", + "description": "Assign an SSH key to a workspace for use when cloning VCS repositories. Pass null for the id to unassign the current SSH key.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "type": { + "type": "string", + "enum": [ + "ssh-keys" + ] + }, + "id": { + "type": "string", + "nullable": true, + "description": "The external ID of the SSH key to assign, or null to unassign." + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "SSH key assignment updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace or SSH key not found, or user unauthorized", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/relationships/vars": { + "patch": { + "operationId": "updateWorkspaceVars", + "summary": "Update Workspace Variables", + "description": "Batch update workspace variables. Provide an array of variable objects to update. Variables are matched by their external ID.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "sensitive": { + "type": "boolean" + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env" + ] + }, + "hcl": { + "type": "boolean" + }, + "description": { + "type": "string", + "nullable": true + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Variables updated" + }, + "400": { + "description": "Too many variables or invalid request", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to update variables", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Validation error on one or more variables", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/relationships/tag-bindings": { + "get": { + "operationId": "listWorkspaceTagBindings", + "summary": "List Workspace Tags", + "description": "List all tags associated with a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "responses": { + "200": { + "description": "List of tags", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/tag-bindings-request" + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addWorkspaceTagBindings", + "summary": "Add Tag Bindings to a Workspace", + "description": "Add one or more tag bindings to a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/tag-bindings-request" + } + } + } + }, + "responses": { + "204": { + "description": "Tags added" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage tags", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "replaceWorkspaceTagBindings", + "summary": "Replace Tag Bindings in a Workspace", + "description": "Replace all tag bindings in a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/tag-bindings-request" + } + } + } + }, + "responses": { + "204": { + "description": "Tag bindings replaced" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage tag bindings", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/relationships/tags": { + "get": { + "operationId": "listWorkspaceTags", + "summary": "List Workspace Tags", + "description": "List all tags associated with a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "200": { + "description": "List of tags", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tags" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addWorkspaceTags", + "summary": "Add Tags to a Workspace", + "description": "Add one or more tags to a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "tags" + ] + }, + "id": { + "type": "string", + "description": "The ID of an existing tag to associate with the workspace." + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of a new tag to create and associate." + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Tags added" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage tags", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeWorkspaceTags", + "summary": "Remove Tags from a Workspace", + "description": "Remove one or more tags from a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "tags" + ] + }, + "id": { + "type": "string", + "description": "The ID of the tag to remove from the workspace." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Tags removed" + }, + "404": { + "description": "Workspace not found or user unauthorized to manage tags", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/current-state-version": { + "get": { + "operationId": "getCurrentStateVersion", + "summary": "Get Current State Version", + "description": "Get the current state version for a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optionally side-load relationships. For example, outputs or created-by.\n" + } + ], + "responses": { + "200": { + "description": "Current state version details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "size": { + "type": "integer", + "nullable": true + }, + "hosted-state-download-url": { + "type": "string", + "nullable": true + }, + "hosted-json-state-download-url": { + "type": "string", + "nullable": true + }, + "modules": { + "type": "object", + "nullable": true + }, + "providers": { + "type": "object", + "nullable": true + }, + "resources": { + "type": "array", + "nullable": true, + "items": { + "type": "object" + } + }, + "resources-processed": { + "type": "boolean" + }, + "serial": { + "type": "integer", + "nullable": true + }, + "state-version": { + "type": "integer", + "nullable": true + }, + "status": { + "type": "string", + "nullable": true + }, + "terraform-version": { + "type": "string", + "nullable": true + } + } + } + } + }, + "included": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found, no current state version exists, or user unauthorized", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/current-assessment-result": { + "get": { + "operationId": "getCurrentAssessmentResult", + "summary": "Get Current Assessment Result", + "description": "Get the most recent drift detection assessment result for a workspace.", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + } + ], + "responses": { + "200": { + "description": "Current assessment result", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "assessment-results" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "drifted": { + "type": "boolean", + "nullable": true + }, + "status": { + "type": "string", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Workspace not found, no current assessment result exists, or user unauthorized", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/applicable-varsets": { + "get": { + "operationId": "listApplicableVarsets", + "summary": "List Applicable Variable Sets", + "description": "List the variable sets that can be applied to a workspace. This returns variable sets from the workspace's organization that are not already applied to the workspace, filtered by project scope.\n", + "tags": [ + "workspaces" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The external ID of the workspace." + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optional search query to filter variable sets by name." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of applicable variable sets", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "varsets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "global": { + "type": "boolean" + }, + "auto-apply": { + "type": "boolean" + }, + "var-count": { + "type": "integer" + }, + "workspace-count": { + "type": "integer" + }, + "project-count": { + "type": "integer" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + } + } + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + }, + "status-counts": { + "type": "object", + "additionalProperties": { + "type": "integer" + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to view workspace", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs": { + "post": { + "operationId": "createRun", + "summary": "Create a Run", + "description": "Create a new run.", + "tags": [ + "runs" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/run" + } + } + } + }, + "responses": { + "201": { + "description": "Run created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/run" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "get": { + "operationId": "listRuns", + "summary": "List Runs", + "description": "List all runs in a workspace.", + "tags": [ + "runs" + ], + "parameters": [ + { + "in": "query", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Workspace ID" + }, + { + "in": "query", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization Name" + }, + { + "in": "query", + "name": "filter[operation]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by run operation." + }, + { + "in": "query", + "name": "filter[status]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by run status." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of runs", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/run" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}": { + "get": { + "operationId": "getRun", + "summary": "Get Run details", + "description": "Get details about a run.", + "tags": [ + "runs" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Run ID" + } + ], + "responses": { + "200": { + "description": "Run details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/run" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}/configuration-version": { + "get": { + "operationId": "getRunConfigurationVersion", + "summary": "Get Run Configuration Version", + "description": "Get details of a specific configuration version.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run" + } + ], + "responses": { + "200": { + "description": "Configuration version details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/configuration-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}/configuration-version/download": { + "get": { + "operationId": "downloadRunConfigurationVersion", + "summary": "Download Run Configuration Version", + "description": "Generate a temporary URL to download the configuration version files.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run." + } + ], + "responses": { + "302": { + "description": "Temporary download URL generated", + "headers": { + "Location": { + "description": "Storage URL to .tar.gz file containing the configuration version", + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}/comments": { + "get": { + "operationId": "listRunComments", + "summary": "List Comments for a Run", + "description": "List all comments for a run.", + "tags": [ + "comments" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Run ID" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of comments", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace-comment" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createRunComment", + "summary": "Create a Comment", + "description": "Create a new comment on a run.", + "tags": [ + "comments" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Run ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/workspace-comment" + } + } + } + }, + "responses": { + "201": { + "description": "Comment created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-comment" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/comments/{id}": { + "get": { + "operationId": "showComment", + "summary": "Show a Comment", + "description": "Get details about a comment.", + "tags": [ + "comments" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Comment ID" + } + ], + "responses": { + "200": { + "description": "Comment details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-comment" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}/actions/apply": { + "post": { + "operationId": "applyRun", + "summary": "Apply a Run", + "description": "Apply a run that is paused waiting for confirmation.", + "tags": [ + "runs" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Run ID" + } + ], + "requestBody": { + "required": false, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "comment": { + "type": "string", + "nullable": true + } + } + } + } + } + }, + "responses": { + "202": { + "description": "Successfully queued an apply request" + }, + "409": { + "description": "Run was not paused for confirmation; apply not allowed.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/runs": { + "get": { + "operationId": "listWorkspaceRuns", + "summary": "List Runs in a Workspace", + "description": "List all runs in a workspace.", + "tags": [ + "runs" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Workspace ID" + }, + { + "in": "query", + "name": "filter[operation]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by run operation." + }, + { + "in": "query", + "name": "filter[status]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by run status." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of runs", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/run" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/run-triggers": { + "get": { + "operationId": "listRunTriggers", + "summary": "List Run Triggers", + "description": "List all run triggers for a workspace.", + "tags": [ + "run-triggers" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Workspace ID" + }, + { + "in": "query", + "name": "filter[run-trigger][type]", + "schema": { + "type": "string", + "enum": [ + "inbound", + "outbound" + ] + }, + "required": true, + "description": "Filter by run trigger type (inbound or outbound)" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of run triggers", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/run-trigger" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createRunTrigger", + "summary": "Create a Run Trigger", + "description": "Create a new run trigger for a workspace.", + "tags": [ + "run-triggers" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Workspace ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/run-trigger" + } + } + } + }, + "responses": { + "201": { + "description": "Run trigger created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/run-trigger" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/run-triggers/{id}": { + "get": { + "operationId": "showRunTrigger", + "summary": "Show a Run Trigger", + "description": "Get details about a run trigger.", + "tags": [ + "run-triggers" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Run Trigger ID" + } + ], + "responses": { + "200": { + "description": "Run trigger details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/run-trigger" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteRunTrigger", + "summary": "Delete a Run Trigger", + "description": "Delete a run trigger.", + "tags": [ + "run-triggers" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Run Trigger ID" + } + ], + "responses": { + "204": { + "description": "Run trigger deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/runs": { + "get": { + "operationId": "listOrganizationRuns", + "summary": "List Runs in an Organization", + "description": "List all runs in an organization.", + "tags": [ + "runs" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization name" + }, + { + "in": "query", + "name": "filter[operation]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by run operation." + }, + { + "in": "query", + "name": "filter[status]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by run status." + }, + { + "in": "query", + "name": "filter[timeframe]", + "schema": { + "type": "string", + "default": "year" + }, + "required": false, + "description": "Filter by timeframe. Must be a numeric year or \"year\" for the last 12 months (the default)." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of runs", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/run" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination-without-totals" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/plans/{id}": { + "get": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The ID of the plan to show.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "showPlan", + "summary": "Show a plan", + "description": "This endpoint returns a specific plan by its ID.", + "tags": [ + "plans" + ], + "responses": { + "200": { + "description": "Successfully returned the plan.", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/plan" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/plans/{id}/json-output": { + "get": { + "operationId": "getPlanJSONOutput", + "summary": "Get the JSON execution plan", + "description": "This endpoint generates a temporary authenticated URL to the location of the JSON formatted execution plan.\nWhen successful, this endpoint responds with a temporary redirect that should be followed.\n\nThis endpoint is available for plans using Terraform 0.12 and later.\nThe temporary URL has a life of 1 minute and should not be relied upon beyond the initial request.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The ID of the plan to show.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "plans" + ], + "responses": { + "204": { + "description": "Plan JSON supported, but plan has not yet completed." + }, + "307": { + "description": "Plan JSON found and temporary download URL generated.", + "headers": { + "Location": { + "description": "Temporary URL to download the JSON output", + "schema": { + "type": "string", + "format": "uri" + } + } + } + }, + "422": { + "description": "Plan does not use a supported version of Terraform (< 0.12.X).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{id}/plan/json-schema": { + "get": { + "operationId": "getPlanJSONSchemaOutput", + "summary": "Get the JSON provider schema corresponding to a plan", + "description": "This endpoint generates a temporary authenticated URL to the location of the JSON formatted provider schema.\nWhen successful, this endpoint responds with a temporary redirect that should be followed.\n\nThis endpoint is available for plans using Terraform 0.12 and later.\nThe temporary URL has a life of 1 minute and should not be relied upon beyond the initial request.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The ID of the plan to show.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "plans" + ], + "responses": { + "204": { + "description": "Plan JSON supported, but plan has not yet completed." + }, + "307": { + "description": "Plan JSON found and temporary download URL generated.", + "headers": { + "Location": { + "description": "Temporary URL to download the JSON schema output", + "schema": { + "type": "string", + "format": "uri" + } + } + } + }, + "422": { + "description": "Plan does not use a supported version of Terraform (< 0.12.X).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{id}/plan": { + "get": { + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The ID of the run whose plan you want to get.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "operationId": "getRunPlan", + "summary": "Get a plan by Run ID", + "description": "This endpoint returns a specific plan by its run ID.", + "tags": [ + "plans" + ], + "responses": { + "200": { + "description": "Successfully returned the plan.", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/plan" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{id}/plan/json-output": { + "get": { + "operationId": "getRunPlanJsonOutput", + "summary": "Get the JSON execution plan by Run ID", + "description": "This endpoint generates a temporary authenticated URL to the location of the JSON formatted execution plan.\nWhen successful, this endpoint responds with a temporary redirect that should be followed.\n\nThis endpoint is available for plans using Terraform 0.12 and later.\nThe temporary URL has a life of 1 minute and should not be relied upon beyond the initial request.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The ID of the run whose plan json you want to get.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "plans" + ], + "responses": { + "204": { + "description": "Plan JSON supported, but plan has not yet completed." + }, + "307": { + "description": "Plan JSON found and temporary download URL generated.", + "headers": { + "Location": { + "description": "Temporary URL to download the JSON output", + "schema": { + "type": "string", + "format": "uri" + } + } + } + }, + "422": { + "description": "Plan does not use a supported version of Terraform (< 0.12.X).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policies/{policy_id}": { + "get": { + "operationId": "showPolicy", + "summary": "Show a Policy", + "description": "Get details about a policy.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "policy_id", + "in": "path", + "required": true, + "description": "The ID of the policy to show.", + "schema": { + "type": "string", + "example": "pol-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updatePolicy", + "summary": "Update a Policy", + "description": "Update the enforcement level or description of an existing policy. To update the policy code itself, use the upload endpoint.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "policy_id", + "in": "path", + "required": true, + "description": "The ID of the policy to update.", + "schema": { + "type": "string", + "example": "pol-xxxxxxxxxxxxxxxx" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "policies" + ] + }, + "attributes": { + "type": "object", + "properties": { + "description": { + "type": "string", + "nullable": true, + "description": "Text describing the policy's purpose." + }, + "query": { + "type": "string", + "nullable": true, + "description": "The OPA query to run. Only valid for OPA policies." + }, + "enforcement-level": { + "type": "string", + "enum": [ + "hard-mandatory", + "soft-mandatory", + "advisory", + "mandatory" + ], + "description": "The enforcement level of the policy." + }, + "enforce": { + "type": "array", + "description": "DEPRECATED: Use enforcement-level instead.", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deletePolicy", + "summary": "Delete a Policy", + "description": "Delete a policy from an organization.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "policy_id", + "in": "path", + "required": true, + "description": "The ID of the policy to delete.", + "schema": { + "type": "string", + "example": "pol-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/policies": { + "get": { + "operationId": "listPolicies", + "summary": "List Policies", + "description": "List all policies for an organization.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "description": "The name of the organization.", + "schema": { + "type": "string", + "example": "my-organization" + } + }, + { + "name": "search[name]", + "in": "query", + "required": false, + "description": "Allows searching the organization's policies by name.", + "schema": { + "type": "string" + } + }, + { + "name": "filter[kind]", + "in": "query", + "required": false, + "description": "Filter policies by kind. Valid values are sentinel and opa.", + "schema": { + "type": "string", + "enum": [ + "sentinel", + "opa" + ] + } + }, + { + "name": "sort", + "in": "query", + "required": false, + "description": "Sort policies by the specified field. Valid values are name, -name, updated-at, and -updated-at. Prefix with - for descending order.", + "schema": { + "type": "string" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createPolicy", + "summary": "Create a Policy", + "description": "Create a new policy object for the organization. After creation, upload the policy code using the upload endpoint.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "description": "The name of the organization.", + "schema": { + "type": "string", + "example": "my-organization" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "policies" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the policy." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Text describing the policy's purpose." + }, + "kind": { + "type": "string", + "enum": [ + "sentinel", + "opa" + ], + "description": "The policy-as-code framework. Defaults to sentinel." + }, + "query": { + "type": "string", + "description": "The OPA query to run. Only valid for OPA policies." + }, + "enforcement-level": { + "type": "string", + "enum": [ + "hard-mandatory", + "soft-mandatory", + "advisory", + "mandatory" + ], + "description": "The enforcement level of the policy." + }, + "enforce": { + "type": "array", + "description": "DEPRECATED: Use enforcement-level instead.", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "string" + } + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "policy-sets": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policy-sets" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policies/{policy_id}/download": { + "get": { + "operationId": "downloadPolicy", + "summary": "Download a Policy", + "description": "Generate a temporary URL to the current version of the policy code and redirect to that location. Returns 404 if no policy code has been uploaded.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "policy_id", + "in": "path", + "required": true, + "description": "The ID of the policy to download.", + "schema": { + "type": "string", + "example": "pol-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "302": { + "description": "Redirect to the temporary download URL for the policy code", + "headers": { + "Location": { + "description": "Temporary storage URL for the policy code", + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policies/{policy_id}/upload": { + "put": { + "operationId": "uploadPolicy", + "summary": "Upload a Policy", + "description": "Upload code to an existing Sentinel or OPA policy. The request body must be the policy code with a Content-Type of application/octet-stream. Policy uploads are limited to 10MB.", + "tags": [ + "policies" + ], + "parameters": [ + { + "name": "policy_id", + "in": "path", + "required": true, + "description": "The ID of the policy to upload code to.", + "schema": { + "type": "string", + "example": "pol-xxxxxxxxxxxxxxxx" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/octet-stream": { + "schema": { + "type": "string", + "format": "binary", + "description": "The policy code as a binary stream." + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-checks/{id}": { + "get": { + "operationId": "getPolicyCheck", + "summary": "Show a Policy Check", + "description": "Get information about a specific policy check.", + "tags": [ + "policy-checks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy check to show." + } + ], + "responses": { + "200": { + "description": "Policy check details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-check" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-checks/{id}/output": { + "get": { + "operationId": "getPolicyCheckOutput", + "summary": "Get Policy Check Output", + "description": "Retrieve the Sentinel output log for a policy check. When output is available, the response redirects to a temporary presigned URL. When no result exists yet, the response is 204 No Content.", + "tags": [ + "policy-checks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy check." + } + ], + "responses": { + "204": { + "description": "No output available yet for this policy check." + }, + "302": { + "description": "Temporary URL generated; follow the redirect to download the output log.", + "headers": { + "Location": { + "description": "Presigned URL pointing to the Sentinel output log.", + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-checks/{id}/actions/override": { + "post": { + "operationId": "overridePolicyCheck", + "summary": "Override a Policy Check", + "description": "Override a soft-mandatory or warning policy check to allow the run to continue.", + "tags": [ + "policy-checks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy check to override." + } + ], + "requestBody": { + "required": false, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "comment": { + "type": "string", + "nullable": true, + "description": "An optional comment explaining the reason for overriding the policy check." + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Policy check successfully overridden", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-check" + } + } + } + } + } + }, + "409": { + "description": "The policy check is not in an overridable state.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}/policy-checks": { + "get": { + "operationId": "listRunPolicyChecks", + "summary": "List Policy Checks for a Run", + "description": "List the policy checks associated with a run.", + "tags": [ + "policy-checks" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run to list policy checks for." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of policy checks", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-check" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/parameters": { + "get": { + "operationId": "listPolicySetParams", + "summary": "List Policy Set Parameters", + "description": "List parameters belonging to a policy set.", + "tags": [ + "policy-set-params" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of policy set parameters", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/var" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createPolicySetParam", + "summary": "Create a Policy Set Parameter", + "description": "Create a new parameter for a policy set.", + "tags": [ + "policy-set-params" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "required": [ + "key", + "category" + ], + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "category": { + "type": "string", + "enum": [ + "policy-set" + ] + }, + "sensitive": { + "type": "boolean" + }, + "description": { + "type": "string", + "nullable": true + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Policy set parameter created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/parameters/{id}": { + "get": { + "operationId": "getPolicySetParam", + "summary": "Get a Policy Set Parameter", + "description": "Get details about a policy set parameter.", + "tags": [ + "policy-set-params" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the parameter." + } + ], + "responses": { + "200": { + "description": "Policy set parameter details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updatePolicySetParam", + "summary": "Update a Policy Set Parameter", + "description": "Update an existing policy set parameter.", + "tags": [ + "policy-set-params" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the parameter to update." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "id": { + "type": "string" + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "category": { + "type": "string", + "enum": [ + "policy-set" + ] + }, + "sensitive": { + "type": "boolean" + }, + "description": { + "type": "string", + "nullable": true + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Policy set parameter updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/var" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deletePolicySetParam", + "summary": "Delete a Policy Set Parameter", + "description": "Delete a policy set parameter.", + "tags": [ + "policy-set-params" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the parameter to delete." + } + ], + "responses": { + "204": { + "description": "Policy set parameter deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}": { + "get": { + "operationId": "getPolicySet", + "summary": "Get a Policy Set", + "description": "Get details about a specific policy set.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "responses": { + "200": { + "description": "Policy set details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-set" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updatePolicySet", + "summary": "Update a Policy Set", + "description": "Update an existing policy set.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "policy-sets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "global": { + "type": "boolean" + }, + "policies-path": { + "type": "string", + "nullable": true + }, + "agent-enabled": { + "type": "boolean" + }, + "policy-tool-version": { + "type": "string", + "nullable": true + }, + "policy-update-patterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "branch": { + "type": "string", + "nullable": true + }, + "identifier": { + "type": "string" + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + }, + "workspace-exclusions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "projects" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Policy set updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-set" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deletePolicySet", + "summary": "Delete a Policy Set", + "description": "Delete a policy set. Deleting a policy set does not delete the policies it contains.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "responses": { + "204": { + "description": "Policy set deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/policy-sets": { + "get": { + "operationId": "listPolicySets", + "summary": "List Policy Sets", + "description": "List all policy sets in an organization.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "filter[versioned]", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "If true, only return versioned policy sets. If false, only return non-versioned policy sets." + }, + { + "in": "query", + "name": "filter[kind]", + "schema": { + "type": "string", + "enum": [ + "sentinel", + "opa", + "tfpolicy" + ] + }, + "required": false, + "description": "Filter policy sets by kind." + }, + { + "in": "query", + "name": "search[name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter policy sets by name." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of policy sets", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-set" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createPolicySet", + "summary": "Create a Policy Set", + "description": "Create a new policy set in an organization.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "policy-sets" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "global": { + "type": "boolean" + }, + "kind": { + "type": "string", + "enum": [ + "sentinel", + "opa", + "tfpolicy" + ] + }, + "agent-enabled": { + "type": "boolean" + }, + "policy-tool-version": { + "type": "string", + "nullable": true + }, + "overridable": { + "type": "boolean" + }, + "policies-path": { + "type": "string", + "nullable": true + }, + "policy-update-patterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "enforcement-level": { + "type": "string", + "nullable": true + }, + "evaluation-stages": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "branch": { + "type": "string", + "nullable": true + }, + "identifier": { + "type": "string" + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "policies": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policies" + ] + } + } + } + } + } + }, + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + }, + "workspace-exclusions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "projects" + ] + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Policy set created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-set" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/relationships/workspaces": { + "post": { + "operationId": "addPolicySetWorkspaces", + "summary": "Add Workspaces to a Policy Set", + "description": "Add workspaces to a policy set. Relationships are additive; existing workspace memberships are preserved.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Workspaces successfully added to policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removePolicySetWorkspaces", + "summary": "Remove Workspaces from a Policy Set", + "description": "Remove workspaces from a policy set. Workspaces not currently in the set are ignored.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Workspaces successfully removed from policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/relationships/policies": { + "post": { + "operationId": "addPolicySetPolicies", + "summary": "Add Policies to a Policy Set", + "description": "Add policies to a policy set. Relationships are additive; existing policy memberships are preserved.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "policies" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Policies successfully added to policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removePolicySetPolicies", + "summary": "Remove Policies from a Policy Set", + "description": "Remove policies from a policy set. Policies not currently in the set are ignored.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "policies" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Policies successfully removed from policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/relationships/projects": { + "post": { + "operationId": "addPolicySetProjects", + "summary": "Add Projects to a Policy Set", + "description": "Add projects to a policy set. Relationships are additive; existing project memberships are preserved.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Projects successfully added to policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removePolicySetProjects", + "summary": "Remove Projects from a Policy Set", + "description": "Remove projects from a policy set. Projects not currently in the set are ignored.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Projects successfully removed from policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/relationships/workspace-exclusions": { + "post": { + "operationId": "addPolicySetWorkspaceExclusions", + "summary": "Add Workspace Exclusions to a Policy Set", + "description": "Add workspace exclusions to a policy set. Excluded workspaces will not have the policy set applied to them even if the set is global.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Workspace exclusions successfully added to policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removePolicySetWorkspaceExclusions", + "summary": "Remove Workspace Exclusions from a Policy Set", + "description": "Remove workspace exclusions from a policy set. Workspace exclusions not currently in the set are ignored.", + "tags": [ + "policy-sets" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Workspace exclusions successfully removed from policy set." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-sets/{policy_set_id}/versions": { + "get": { + "operationId": "listPolicySetVersions", + "summary": "List Policy Set Versions", + "description": "List all versions of a policy set.", + "tags": [ + "policy-set-versions" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of policy set versions", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-set-version" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createPolicySetVersion", + "summary": "Create a Policy Set Version", + "description": "Create a new version for a policy set. The version will be in a pending state until policies are uploaded to it.", + "tags": [ + "policy-set-versions" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set." + } + ], + "responses": { + "201": { + "description": "Policy set version created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-set-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-set-versions/{policy_set_version_id}": { + "get": { + "operationId": "getPolicySetVersion", + "summary": "Get a Policy Set Version", + "description": "Get details about a specific policy set version.", + "tags": [ + "policy-set-versions" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set version." + } + ], + "responses": { + "200": { + "description": "Policy set version details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-set-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-evaluations/{policy_evaluation_id}": { + "get": { + "operationId": "getPolicyEvaluation", + "summary": "Show a Policy Evaluation", + "description": "Get details about a specific policy evaluation.", + "tags": [ + "policy-evaluations" + ], + "parameters": [ + { + "in": "path", + "name": "policy_evaluation_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy evaluation to show." + } + ], + "responses": { + "200": { + "description": "Policy evaluation details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-evaluation" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-evaluations/{policy_evaluation_id}/policy-set-outcomes": { + "get": { + "operationId": "listPolicySetOutcomes", + "summary": "List Policy Set Outcomes", + "description": "List the policy set outcomes associated with a policy evaluation.", + "tags": [ + "policy-evaluations" + ], + "parameters": [ + { + "in": "path", + "name": "policy_evaluation_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy evaluation to list outcomes for." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of policy set outcomes", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-set-outcome" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/policy-set-outcomes/{policy_set_outcome_id}": { + "get": { + "operationId": "getPolicySetOutcome", + "summary": "Show a Policy Set Outcome", + "description": "Get details about a specific policy set outcome.", + "tags": [ + "policy-evaluations" + ], + "parameters": [ + { + "in": "path", + "name": "policy_set_outcome_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the policy set outcome to show." + } + ], + "responses": { + "200": { + "description": "Policy set outcome details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/policy-set-outcome" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-stages/{task_stage_id}/policy-evaluations": { + "get": { + "operationId": "listTaskStagePolicyEvaluations", + "summary": "List Policy Evaluations for a Task Stage", + "description": "List the policy evaluations associated with a task stage.", + "tags": [ + "policy-evaluations" + ], + "parameters": [ + { + "in": "path", + "name": "task_stage_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task stage to list policy evaluations for." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of policy evaluations", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-evaluation" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/plan-exports": { + "post": { + "operationId": "createPlanExport", + "summary": "Create a Plan Export", + "description": "Export data from a plan in the specified format. The export process is asynchronous, and the resulting data becomes downloadable when its status is \"finished\".", + "tags": [ + "plan-exports" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/plan-export" + } + } + } + }, + "responses": { + "201": { + "description": "Plan export created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/plan-export" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/plan-exports/{id}": { + "get": { + "operationId": "showPlanExport", + "summary": "Show a Plan Export", + "description": "Get details about a specific plan export.", + "tags": [ + "plan-exports" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the plan export to show." + } + ], + "responses": { + "200": { + "description": "Plan export details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/plan-export" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deletePlanExport", + "summary": "Delete a Plan Export", + "description": "Delete the exported plan data. Plan exports expire after one hour, but can be deleted manually.", + "tags": [ + "plan-exports" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the plan export to delete." + } + ], + "responses": { + "204": { + "description": "Plan export deleted successfully" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/plan-exports/{id}/download": { + "get": { + "operationId": "downloadPlanExport", + "summary": "Download exported plan data", + "description": "Generate a temporary URL to the location of the exported plan data in a .tar.gz archive, then redirect to that link.", + "tags": [ + "plan-exports" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the plan export to download." + } + ], + "responses": { + "302": { + "description": "Temporary download URL generated", + "headers": { + "Location": { + "description": "Storage URL to .tar.gz archive containing the exported plan data", + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/assessment-results/{id}": { + "get": { + "summary": "Show an assessment result", + "operationId": "getAssessmentResult", + "tags": [ + "assessment-results" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The external ID of the assessment result to show.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The request was successful", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/assessment-result" + } + } + } + } + } + }, + "default": { + "description": "Assessment result not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/assessment-results/{id}/json-output": { + "get": { + "operationId": "getAssessmentResultJSONOutput", + "summary": "Get the JSON assessment output", + "description": "This endpoint returns the JSON formatted assessment output.\nThis is only available when the assessment has succeeded and has JSON output data.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The external ID of the assessment result.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "assessment-results" + ], + "responses": { + "200": { + "description": "Assessment result JSON output found and returned.", + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": true, + "description": "The JSON formatted assessment output with dynamic structure" + } + } + } + }, + "404": { + "description": "Assessment result failed or JSON output is not available.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/assessment-results/{id}/json-schema": { + "get": { + "operationId": "getAssessmentResultJSONSchema", + "summary": "Get the JSON schema", + "description": "This endpoint returns the JSON schema for the assessment result.\nThis is only available when the assessment has succeeded and has provider schemas.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The external ID of the assessment result.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "assessment-results" + ], + "responses": { + "200": { + "description": "JSON schema found and returned.", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "The JSON schema of the assessment result" + } + } + } + }, + "404": { + "description": "Assessment result failed or JSON schema is not available.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/assessment-results/{id}/sanitized-plan": { + "get": { + "operationId": "getAssessmentResultSanitizedPlan", + "summary": "Get the sanitized plan", + "description": "This endpoint returns the sanitized plan for the assessment result.\nThis is only available when HYOK is enabled for the organization,\nthe assessment has succeeded, and a sanitized plan is available.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The external ID of the assessment result.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "tags": [ + "assessment-results" + ], + "responses": { + "200": { + "description": "Sanitized plan found and returned.", + "content": { + "application/json": { + "schema": { + "type": "object", + "description": "The sanitized plan output" + } + } + } + }, + "404": { + "description": "HYOK not available, assessment result failed, or sanitized plan is not available.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/assessment-results/{id}/log-output": { + "get": { + "operationId": "getAssessmentResultLogOutput", + "summary": "Get the log output", + "description": "This endpoint returns the log output for the assessment result.\nSupports both JSON and plain text formats based on the Accept header.\nQuery parameters allow for pagination of log output.\n", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The external ID of the assessment result.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Maximum number of bytes to return", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "offset", + "in": "query", + "description": "Byte offset to start reading from", + "required": false, + "schema": { + "type": "integer" + } + }, + { + "name": "tail", + "in": "query", + "description": "If true, return the last N bytes instead of the first N bytes", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "tags": [ + "assessment-results" + ], + "responses": { + "200": { + "description": "Log output returned successfully.", + "content": { + "text/plain": { + "schema": { + "type": "string", + "description": "The log output in plain text format" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/applies/{id}": { + "get": { + "summary": "Show an apply", + "operationId": "getApply", + "tags": [ + "applies" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the apply to show.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The request was successful", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/apply" + } + } + } + } + } + }, + "default": { + "description": "Apply not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/applies/{id}/errored-state": { + "get": { + "summary": "Recover a failed state upload after applying", + "operationId": "getApplyErroredState", + "tags": [ + "applies" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the apply to recover state for.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "307": { + "description": "Errored state available and user is authorized to read it", + "headers": { + "Location": { + "description": "Storage URL to raw state file", + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Apply not found, errored state not uploaded, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + } + } + }, + "/cost-estimates/{id}": { + "get": { + "summary": "Show a cost estimate", + "operationId": "showCostEstimate", + "tags": [ + "cost-estimates" + ], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "description": "The ID of the cost estimate to show.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The request was successful", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/cost-estimate" + } + } + } + } + } + }, + "default": { + "description": "Cost estimate not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/state-versions": { + "get": { + "operationId": "listStateVersions", + "summary": "List State Versions for a Workspace", + "description": "List state versions for a workspace, filtered by organization and workspace name.", + "tags": [ + "state-versions" + ], + "parameters": [ + { + "in": "query", + "name": "filter[workspace][name]", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the workspace to list state versions for." + }, + { + "in": "query", + "name": "filter[organization][name]", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization that owns the workspace." + }, + { + "in": "query", + "name": "filter[status]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter state versions by status. One or more comma-separated values from pending, finalized, or discarded." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of state versions", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/state-version" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/state-versions/{state_version_id}": { + "get": { + "operationId": "getStateVersion", + "summary": "Show a State Version", + "description": "Show details for a specific state version.", + "tags": [ + "state-versions" + ], + "parameters": [ + { + "in": "path", + "name": "state_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the state version to show." + } + ], + "responses": { + "200": { + "description": "State version details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/state-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/state-versions/{state_version_id}/outputs": { + "get": { + "operationId": "listStateVersionOutputs", + "summary": "List State Version Outputs", + "description": "List the output values associated with a specific state version.", + "tags": [ + "state-versions" + ], + "parameters": [ + { + "in": "path", + "name": "state_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the state version whose outputs to list." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of state version outputs", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/state-version-output" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/state-versions": { + "post": { + "operationId": "createStateVersion", + "summary": "Create a State Version", + "description": "Create a state version and set it as the current state version for the given workspace. The workspace must be locked by the user creating the state version.", + "tags": [ + "state-versions" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace to create the state version in." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + }, + "attributes": { + "type": "object", + "required": [ + "serial", + "md5" + ], + "properties": { + "serial": { + "type": "integer", + "description": "The serial number of the state version." + }, + "md5": { + "type": "string", + "description": "An MD5 hash of the raw state file." + }, + "lineage": { + "type": "string", + "description": "The lineage of the state version." + }, + "state": { + "type": "string", + "description": "Base64 encoded raw state file." + }, + "json-state": { + "type": "string", + "description": "Base64 encoded JSON state, as expressed by terraform show -json." + }, + "json-state-outputs": { + "type": "string", + "description": "Base64 encoded output values as represented by terraform show -json." + }, + "force": { + "type": "boolean", + "description": "Force the state version to be created even if the serial or lineage conflicts." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "run": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "runs" + ] + }, + "id": { + "type": "string" + } + } + } + } + }, + "hyok-encrypted-data-key": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "hyok-encrypted-data-keys" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "State version created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/state-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "rollbackStateVersion", + "summary": "Rollback to a Previous State Version", + "description": "Create a state version by duplicating the specified state version and set it as the current state version for the given workspace. The workspace must be locked by the user performing the rollback.", + "tags": [ + "state-versions" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace to rollback the state version in." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "relationships" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + }, + "relationships": { + "type": "object", + "required": [ + "rollback-state-version" + ], + "properties": { + "rollback-state-version": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + }, + "id": { + "type": "string", + "description": "The ID of the state version to use for the rollback." + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "State version rollback created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/state-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/state-version-outputs/{state_version_output_id}": { + "get": { + "operationId": "getStateVersionOutput", + "summary": "Show a State Version Output", + "description": "Show details for a specific state version output.", + "tags": [ + "state-version-outputs" + ], + "parameters": [ + { + "name": "state_version_output_id", + "in": "path", + "required": true, + "description": "The ID of the state version output to show.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The request was successful", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/state-version-output" + } + } + } + } + } + }, + "default": { + "description": "State version output not found or user not authorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/current-state-version-outputs": { + "get": { + "operationId": "getCurrentStateVersionOutputs", + "summary": "Show Current State Version Outputs for a Workspace", + "description": "List the current state version outputs for a workspace. Sensitive output values are not revealed and will be returned as null. Organization users who do not have permission to read state versions may use this endpoint to fetch the latest output values for a workspace.", + "tags": [ + "state-version-outputs" + ], + "parameters": [ + { + "name": "workspace_id", + "in": "path", + "required": true, + "description": "The ID of the workspace to read outputs from.", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The request was successful", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/state-version-output" + } + } + } + } + } + } + }, + "503": { + "description": "State version outputs are being processed and are not yet ready. Retry the request.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "State version outputs not found or user not authorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/authentication-tokens/{id}": { + "get": { + "operationId": "getAuthenticationToken", + "summary": "Get authentication token details", + "description": "Get details about an authentication token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "ID - Can be a token ID or a team ID, depending on the token type" + } + ], + "responses": { + "200": { + "description": "Authentication Token details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/authentication-token" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error Details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createAuthenticationToken", + "summary": "Create Authentication Token", + "description": "Create an authentication token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "ID - Can be a token ID or a team ID, depending on the token type" + } + ], + "responses": { + "201": { + "description": "Authentication token created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/authentication-token" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAuthenticationToken", + "summary": "Delete authentication Token", + "description": "Delete an authentication token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "ID - Can be a token ID or a team ID, depending on the token type" + } + ], + "responses": { + "204": { + "description": "Authentication token deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/users/{user_id}": { + "get": { + "operationId": "showUser", + "summary": "Show User", + "description": "Shows details for a given user.", + "tags": [ + "users" + ], + "parameters": [ + { + "in": "path", + "name": "user_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the desired user." + } + ], + "responses": { + "200": { + "description": "User details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/user" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/users/{user_id}/github-app-oauth-tokens": { + "get": { + "operationId": "listUserGithubAppOauthTokens", + "summary": "List User GitHub App OAuth Tokens", + "description": "List GitHub App OAuth tokens for a given user.", + "tags": [ + "users" + ], + "parameters": [ + { + "in": "path", + "name": "user_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the user." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "GitHub App OAuth tokens", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/github-app-oauth-token" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/users/{user_id}/authentication-tokens": { + "get": { + "operationId": "listUserTokens", + "summary": "List User Tokens", + "description": "List all tokens for a specified user", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "user_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "User ID" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/authentication-token" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createUserToken", + "summary": "Create User Token", + "description": "Create a user token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "user_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "User ID" + } + ], + "responses": { + "201": { + "description": "User token created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/authentication-token" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/agent-pools/{agent_pool_id}/authentication-tokens": { + "get": { + "operationId": "listAgentTokens", + "summary": "List Agent Tokens", + "description": "List all tokens for the specified agent pool.", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "agent_pool_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the Agent Pool" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/authentication-token" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createAgentToken", + "summary": "Create Agent Token", + "description": "Create an agent token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "agent_pool_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the Agent Pool" + } + ], + "responses": { + "201": { + "description": "Agent token created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/authentication-token" + } + } + } + } + } + }, + "404": { + "description": "Agent Pool not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "500": { + "description": "Failure during Agent Token creation", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/teams/{id}/authentication-token": { + "get": { + "operationId": "getAuthenticationToken", + "summary": "Get authentication token details", + "description": "Get details about an authentication token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "ID - Can be a token ID or a team ID, depending on the token type" + } + ], + "responses": { + "200": { + "description": "Authentication Token details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/authentication-token" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error Details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createAuthenticationToken", + "summary": "Create Authentication Token", + "description": "Create an authentication token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "ID - Can be a token ID or a team ID, depending on the token type" + } + ], + "responses": { + "201": { + "description": "Authentication token created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/authentication-token" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteAuthenticationToken", + "summary": "Delete authentication Token", + "description": "Delete an authentication token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "ID - Can be a token ID or a team ID, depending on the token type" + } + ], + "responses": { + "204": { + "description": "Authentication token deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organization/audit-trail": { + "x-vis": [ + "hcpt" + ], + "get": { + "operationId": "showOrganizationAuditTrail", + "summary": "List organization audit events", + "description": "Returns a list of audit events for the organization associated with the authentication token. HCP Terraform retains 14 days of audit log information. Unlike most HCP Terraform APIs, this endpoint does not use the JSON:API specification. This endpoint requires an organization token or an audit trail token; user tokens and team tokens are not accepted.", + "tags": [ + "audit-trails" + ], + "parameters": [ + { + "in": "query", + "name": "since", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "description": "Returns only audit events created after this date. Must be a UTC ISO8601 datetime string (YYYY-MM-DDTHH:MM:SS.SSSZ)." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Audit events list", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of this audit event." + }, + "version": { + "type": "string", + "description": "The audit trail schema version." + }, + "type": { + "type": "string", + "description": "The type of audit event (defaults to \"Resource\")." + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "UTC ISO8601 timestamp of the event." + }, + "auth": { + "type": "object", + "properties": { + "accessor_id": { + "type": "string", + "description": "The ID of the audited actor." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Username of the audited actor." + }, + "type": { + "type": "string", + "nullable": true, + "description": "Authentication type. One of \"Client\", \"Impersonated\", or \"System\"." + }, + "impersonator_id": { + "type": "string", + "nullable": true, + "description": "The ID of the impersonating actor, if available." + }, + "organization_id": { + "type": "string", + "description": "The ID of the organization." + } + } + }, + "request": { + "type": "object", + "properties": { + "id": { + "type": "string", + "nullable": true, + "description": "The ID of the request, if available." + } + } + }, + "resource": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the audited resource." + }, + "type": { + "type": "string", + "description": "The type of the audited resource (e.g., \"run\")." + }, + "action": { + "type": "string", + "description": "The action that was audited (e.g., \"applied\")." + }, + "meta": { + "type": "object", + "nullable": true, + "additionalProperties": true, + "description": "Key-value metadata about the audited event. Defaults to null." + } + } + } + } + } + }, + "pagination": { + "type": "object", + "properties": { + "current_page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "prev_page": { + "type": "integer", + "nullable": true + }, + "next_page": { + "type": "integer", + "nullable": true + }, + "total_pages": { + "type": "integer" + }, + "total_count": { + "type": "integer" + } + } + } + } + } + } + } + }, + "default": { + "description": "Unauthorized or forbidden", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/authentication-token": { + "get": { + "operationId": "getOrganizationToken", + "summary": "Get organization token details", + "description": "Get details about an organization token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization name" + } + ], + "responses": { + "200": { + "description": "Organization Token details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/authentication-token" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error Details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createOrganizationToken", + "summary": "Create Organization Token", + "description": "Create an organization token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization name" + } + ], + "responses": { + "200": { + "description": "Organization token created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "included": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/authentication-token" + } + ] + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteOrganizationToken", + "summary": "Delete organization Token", + "description": "Delete an organization token", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization name" + } + ], + "responses": { + "204": { + "description": "Organization token deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/team-tokens": { + "get": { + "operationId": "listTeamTokensForAnOrganization", + "summary": "List Team Tokens for an Organization", + "description": "List all tokens for a specified organization", + "tags": [ + "authentication-tokens" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Organization Name" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/authentication-token" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/teams": { + "get": { + "operationId": "listTeams", + "summary": "List Teams", + "description": "List teams in an organization. Any member of an organization can view visible teams and any secret teams they are a member of.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Name of the organization" + }, + { + "in": "query", + "name": "q", + "schema": { + "type": "string" + }, + "required": false, + "description": "A search query string. Teams are searchable by name (case-insensitive)." + }, + { + "in": "query", + "name": "filter[names]", + "schema": { + "type": "string" + }, + "required": false, + "description": "If specified, restricts results to a team with a matching name. If multiple comma separated values are specified, teams matching any of the names are returned." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "users", + "organization-memberships" + ] + }, + "required": false, + "description": "Optionally side-load relationships. Can include \"users\" or \"organization-memberships\"." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "Teams list", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/team" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/user" + }, + { + "$ref": "#/components/schemas/organization-membership" + } + ] + } + } + } + } + } + } + }, + "400": { + "description": "Invalid include parameter", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createTeam", + "summary": "Create Team", + "description": "Create a team in an organization.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "Name of the organization" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/team" + } + } + } + }, + "responses": { + "200": { + "description": "Team created successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/team" + } + } + } + } + } + }, + "400": { + "description": "Invalid include parameter", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Organization not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/teams/{team_id}": { + "get": { + "operationId": "getTeam", + "summary": "Show Team Information", + "description": "Get details about a team.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Team ID" + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string", + "enum": [ + "users", + "organization-memberships" + ] + }, + "required": false, + "description": "Optionally side-load relationships. Can include \"users\" or \"organization-memberships\"." + } + ], + "responses": { + "200": { + "description": "Team details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/team" + }, + "included": { + "type": "array", + "items": { + "anyOf": [ + { + "$ref": "#/components/schemas/user" + }, + { + "$ref": "#/components/schemas/organization-membership" + } + ] + } + } + } + } + } + } + }, + "400": { + "description": "Invalid include parameter", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateTeam", + "summary": "Update Team", + "description": "Update a team's attributes.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Team ID" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/team" + } + } + } + }, + "responses": { + "200": { + "description": "Team updated successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/team" + } + } + } + } + } + }, + "400": { + "description": "Invalid include parameter", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteTeam", + "summary": "Delete Team", + "description": "Delete a team. Only organization owners can delete teams.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "Team ID" + } + ], + "responses": { + "204": { + "description": "Team deleted successfully" + }, + "404": { + "description": "Team not found, or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/teams/{team_id}/relationships/users": { + "post": { + "operationId": "addTeamMembersByUsername", + "summary": "Add Users to Team (by username)", + "description": "Add multiple users to a team using their usernames. Both users and teams must already exist.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "users" + ] + }, + "id": { + "type": "string", + "description": "The username of the user to add to the team." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Users successfully added to team." + }, + "400": { + "description": "Invalid request (blank ID, wrong type, user does not exist, user is already a member, user is not in the organization).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "403": { + "description": "Forbidden. The organization is managed by HCP.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeTeamMembersByUsername", + "summary": "Remove Users from Team (by username)", + "description": "Remove multiple users from a team using their usernames. This only removes users from this team; it does not delete the users from the organization.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "users" + ] + }, + "id": { + "type": "string", + "description": "The username of the user to remove from the team." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Users successfully removed from team." + }, + "400": { + "description": "Invalid request (blank ID, wrong type, user is not a member).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "403": { + "description": "Forbidden. The organization is managed by HCP, or attempting to remove the last owner of the owners team.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/teams/{team_id}/relationships/organization-memberships": { + "get": { + "operationId": "listTeamOrganizationMemberships", + "summary": "List Team Organization Memberships", + "description": "List all organization memberships for a team. Returns both active members and invited users.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + }, + { + "in": "query", + "name": "filter[status]", + "schema": { + "type": "string", + "enum": [ + "active", + "invited" + ] + }, + "required": false, + "description": "Filter memberships by status." + }, + { + "in": "query", + "name": "filter[is_service_account]", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "required": false, + "description": "Filter to include only service account members." + }, + { + "in": "query", + "name": "sort", + "schema": { + "type": "string", + "enum": [ + "status", + "-status" + ] + }, + "required": false, + "description": "Sort memberships. Prefix with '-' for descending order (e.g. '-status')." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of organization memberships for the team.", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/organization-membership" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "400": { + "description": "Invalid filter or sort parameter.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addTeamMembersByOrgMembership", + "summary": "Add Users to Team (by organization membership ID)", + "description": "Add multiple users to a team using their organization membership IDs. Unlike the username method, users only need a pending invitation to the organization.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "organization-memberships" + ] + }, + "id": { + "type": "string", + "description": "The organization membership ID of the user to add." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Users successfully added to team." + }, + "400": { + "description": "Invalid request (blank ID, wrong type, membership does not exist, user is already a member, user is not in the organization).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "403": { + "description": "Forbidden. The organization is managed by HCP.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeTeamMembersByOrgMembership", + "summary": "Remove Users from Team (by organization membership ID)", + "description": "Remove multiple users from a team using their organization membership IDs. This only removes users from this team; it does not delete the users from the organization.", + "tags": [ + "teams" + ], + "parameters": [ + { + "in": "path", + "name": "team_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "organization-memberships" + ] + }, + "id": { + "type": "string", + "description": "The organization membership ID of the user to remove." + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "Users successfully removed from team." + }, + "400": { + "description": "Invalid request (blank ID, wrong type, membership does not exist, user is not a member).", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "403": { + "description": "Forbidden. The organization is managed by HCP, or attempting to remove the last active owner of the owners team.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "404": { + "description": "Team not found, or user unauthorized to perform action.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/team-projects": { + "get": { + "operationId": "listTeamProjects", + "summary": "List Team Access to a Project", + "description": "List all team access grants for a project.", + "tags": [ + "team-projects" + ], + "parameters": [ + { + "in": "query", + "name": "filter[project][id]", + "schema": { + "type": "string" + }, + "required": true, + "description": "The project ID to list team access for." + }, + { + "in": "query", + "name": "filter[team][id]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Optionally filter by team ID." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of team-project access grants", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/team-project" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "404": { + "description": "Project not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addProjectTeamAccess", + "summary": "Add Team Access to a Project", + "description": "Add a team's access to a project.", + "tags": [ + "team-projects" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/team-project" + } + } + } + }, + "responses": { + "201": { + "description": "Team access created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/team-project" + } + } + } + } + } + }, + "404": { + "description": "Project or team not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/team-projects/{team_project_id}": { + "get": { + "operationId": "showProjectTeamAccess", + "summary": "Show a Team Access Relationship", + "description": "Get details about a team's access to a project.", + "tags": [ + "team-projects" + ], + "parameters": [ + { + "in": "path", + "name": "team_project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team/project relationship." + } + ], + "responses": { + "200": { + "description": "Team-project access details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/team-project" + } + } + } + } + } + }, + "404": { + "description": "Team access not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateProjectTeamAccess", + "summary": "Update Team Access to a Project", + "description": "Update a team's access level on a project.", + "tags": [ + "team-projects" + ], + "parameters": [ + { + "in": "path", + "name": "team_project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team/project relationship." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/team-project" + } + } + } + }, + "responses": { + "200": { + "description": "Team access updated successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/team-project" + } + } + } + } + } + }, + "404": { + "description": "Team access not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeProjectTeamAccess", + "summary": "Remove Team Access from a Project", + "description": "Remove a team's access from a project.", + "tags": [ + "team-projects" + ], + "parameters": [ + { + "in": "path", + "name": "team_project_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the team/project relationship." + } + ], + "responses": { + "204": { + "description": "Team access removed successfully" + }, + "404": { + "description": "Team access not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/team-workspaces": { + "get": { + "operationId": "listTeamWorkspaces", + "summary": "List Team Access to a Workspace", + "description": "List all team access relationships. Optionally filter by workspace or team ID.", + "tags": [ + "team-access" + ], + "parameters": [ + { + "in": "query", + "name": "filter[workspace][id]", + "schema": { + "type": "string" + }, + "required": false, + "description": "The workspace ID to list team access for." + }, + { + "in": "query", + "name": "filter[team][id]", + "schema": { + "type": "string" + }, + "required": false, + "description": "The team ID to list workspace access for." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of team access relationships", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/team-workspace" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "404": { + "description": "Workspace not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "addTeamAccess", + "summary": "Add Team Access to a Workspace", + "description": "Add a team's access to a workspace.", + "tags": [ + "team-access" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/team-workspace" + } + } + } + }, + "responses": { + "201": { + "description": "Team access relationship created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/team-workspace" + } + } + } + } + } + }, + "404": { + "description": "Workspace or Team not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/team-workspaces/{team_workspace_id}": { + "get": { + "operationId": "showTeamAccess", + "summary": "Show a Team Access Relationship", + "description": "Get details about a team's access to a workspace.", + "tags": [ + "team-access" + ], + "parameters": [ + { + "in": "path", + "name": "team_workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The team/workspace relationship ID." + } + ], + "responses": { + "200": { + "description": "Team access relationship details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/team-workspace" + } + } + } + } + } + }, + "404": { + "description": "Team access not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateTeamAccess", + "summary": "Update Team Access to a Workspace", + "description": "Update a team's access to a workspace.", + "tags": [ + "team-access" + ], + "parameters": [ + { + "in": "path", + "name": "team_workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The team/workspace relationship ID." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/team-workspace" + } + } + } + }, + "responses": { + "200": { + "description": "Team access relationship updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/team-workspace" + } + } + } + } + } + }, + "404": { + "description": "Team access not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Malformed request body (missing attributes, wrong types, etc.)", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "removeTeamAccess", + "summary": "Remove Team Access to a Workspace", + "description": "Remove a team's access to a workspace.", + "tags": [ + "team-access" + ], + "parameters": [ + { + "in": "path", + "name": "team_workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The team/workspace relationship ID." + } + ], + "responses": { + "204": { + "description": "Team access relationship deleted" + }, + "404": { + "description": "Team access not found or user unauthorized to perform action", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/tasks/integrations": { + "get": { + "tags": [ + "tasks" + ], + "summary": "List Integrations", + "description": "List all available integrations that can be used with tasks. \nBy default, only active integrations are returned.\n", + "parameters": [ + { + "name": "search", + "in": "query", + "required": false, + "description": "Search integrations by name (case-insensitive, partial match).", + "schema": { + "type": "string", + "example": "cloud" + } + }, + { + "name": "category", + "in": "query", + "required": false, + "description": "Filter integrations by category.", + "schema": { + "type": "string", + "example": "cost-estimation" + } + }, + { + "name": "include_inactive", + "in": "query", + "required": false, + "description": "Include inactive integrations in the results.", + "schema": { + "type": "string", + "enum": [ + "true", + "false" + ], + "default": "false" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/integration" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/configuration-versions": { + "get": { + "operationId": "listConfigurationVersions", + "summary": "List Configuration Versions", + "description": "List configuration versions for a workspace.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of configuration versions", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/configuration-version" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createConfigurationVersion", + "summary": "Create Configuration Version", + "description": "Create a new configuration version in a workspace.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/configuration-version" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Configuration version created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/configuration-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/configuration-versions/{configuration_version_id}": { + "get": { + "operationId": "getConfigurationVersion", + "summary": "Get Configuration Version", + "description": "Get details of a specific configuration version.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "configuration_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the configuration version." + } + ], + "responses": { + "200": { + "description": "Configuration version details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/configuration-version" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/configuration-versions/{configuration_version_id}/ingress-attributes": { + "get": { + "operationId": "getIngressAttributes", + "summary": "Get Ingress Attributes", + "description": "Get commit information for a configuration version.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "configuration_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the configuration version." + } + ], + "responses": { + "200": { + "description": "Ingress attributes details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/ingress-attributes" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/configuration-versions/{configuration_version_id}/actions/archive": { + "post": { + "operationId": "archiveConfigurationVersion", + "summary": "Archive Configuration Version", + "description": "Archive the uploaded files for a configuration version.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "configuration_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the configuration version." + } + ], + "responses": { + "202": { + "description": "Archive process initiated" + }, + "409": { + "description": "Configuration version was in a non-archivable state or the configuration version was created with VCS and cannot be archived through the API.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/configuration-versions/{configuration_version_id}/download": { + "get": { + "operationId": "downloadConfigurationVersion", + "summary": "Download Configuration Version", + "description": "Generate a temporary URL to download the configuration version files.", + "tags": [ + "configuration-versions" + ], + "parameters": [ + { + "in": "path", + "name": "configuration_version_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the configuration version." + } + ], + "responses": { + "302": { + "description": "Temporary download URL generated", + "headers": { + "Location": { + "description": "Storage URL to .tar.gz file containing the configuration version", + "schema": { + "type": "string" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/vcs-events": { + "get": { + "operationId": "listOrganizationVcsEvents", + "summary": "List VCS Events", + "description": "List VCS events for an organization.", + "tags": [ + "vcs-events" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization to list VCS events from." + }, + { + "in": "query", + "name": "filter[from]", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "description": "RFC3339 formatted UTC timestamp. If omitted, defaults to 10 days ago." + }, + { + "in": "query", + "name": "filter[to]", + "schema": { + "type": "string", + "format": "date-time" + }, + "required": false, + "description": "RFC3339 formatted UTC timestamp. If omitted, defaults to now." + }, + { + "in": "query", + "name": "filter[oauth_client_external_ids]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Comma-separated list of OAuth client external IDs to filter by." + }, + { + "in": "query", + "name": "filter[levels]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Comma-separated list of event levels to filter by. Accepted values are \"info\" and \"error\"." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Allows including related resource data. Only \"oauth_client\" is supported." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of VCS events", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/vcs-event" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/vcs/tree": { + "get": { + "operationId": "getVcsTree", + "summary": "List directories in a repository", + "description": "This endpoint returns a list of directories in a repository \nat the root or at a specific reference (branch, tag, or commit SHA).\nNote: This endpoint only returns directories, not files.\n", + "tags": [ + "vcs" + ], + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "The name of the organization" + }, + { + "name": "oauth_token_id", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The OAuth token ID to authenticate with the VCS provider" + }, + { + "name": "identifier", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The repository identifier (e.g., \"owner/repo\")" + }, + { + "name": "branch", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "The branch, tag, or commit SHA to list directories for. \nIf not provided, the default branch will be used.\n" + }, + { + "name": "githubAppInstallationId", + "in": "query", + "required": false, + "schema": { + "type": "string" + }, + "description": "The GitHub App installation ID (only needed when using GitHub App authentication)" + } + ], + "responses": { + "200": { + "description": "Successfully retrieved repository directories", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the directory" + }, + "type": { + "type": "string", + "enum": [ + "vcs-tree" + ] + } + } + } + } + } + } + } + } + }, + "404": { + "description": "Repository not found or user doesn't have access" + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/organizations/{organization_name}/vcs/repo": { + "get": { + "operationId": "checkVcsRepository", + "summary": "Check if a repository exists", + "description": "This endpoint checks if a repository exists and is accessible to the user.\n", + "tags": [ + "vcs" + ], + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "The name of the organization" + }, + { + "name": "oauth_token_id", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The OAuth token ID to authenticate with the VCS provider" + }, + { + "name": "identifier", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The repository identifier (e.g., \"owner/repo\")" + } + ], + "responses": { + "200": { + "description": "Successfully checked repository existence", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "An identifier for the repository check (typically the repository identifier)" + }, + "type": { + "type": "string", + "enum": [ + "vcs-repo-check" + ] + }, + "attributes": { + "type": "object", + "properties": { + "exists": { + "type": "boolean", + "description": "Whether the repository exists and is accessible" + }, + "identifier": { + "type": "string", + "description": "The repository identifier that was checked" + } + } + } + } + } + } + } + } + } + }, + "404": { + "description": "OAuth token not found or user doesn't have access" + } + }, + "security": [ + { + "bearerAuth": [] + } + ] + } + }, + "/organizations/{organization_name}/registry-modules/validation": { + "get": { + "operationId": "validateRegistryModuleNames", + "summary": "Check if a module name and provider combination is available", + "description": "This endpoint checks if a module name and provider combination is available for use within an organization.\nIt returns a validation result indicating whether the name is already in use.\n", + "tags": [ + "registry" + ], + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "The name of the organization" + }, + { + "name": "name", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The name of the module to validate" + }, + { + "name": "provider", + "in": "query", + "required": true, + "schema": { + "type": "string" + }, + "description": "The provider of the module to validate" + } + ], + "responses": { + "200": { + "description": "Successfully validated the module name and provider", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for this validation result" + }, + "type": { + "type": "string", + "enum": [ + "registry-module-address-validations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "module-name": { + "type": "string", + "description": "The module name that was validated" + }, + "provider-name": { + "type": "string", + "description": "The provider name that was validated" + }, + "valid": { + "type": "boolean", + "description": "Whether the module name and provider combination is available" + } + } + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad request" + }, + "401": { + "description": "Unauthorized" + }, + "404": { + "description": "Organization not found" + } + } + } + }, + "/organizations/{organization_name}/ssh-keys": { + "get": { + "tags": [ + "ssh-keys" + ], + "summary": "List SSH Keys", + "description": "List all SSH keys for an organization.", + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "description": "The name of the organization.", + "schema": { + "type": "string", + "example": "my-organization" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ssh-key" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "tags": [ + "ssh-keys" + ], + "summary": "Create an SSH Key", + "description": "Create a new SSH key for an organization.", + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "description": "The name of the organization.", + "schema": { + "type": "string", + "example": "my-organization" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "ssh-keys" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name", + "value" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the SSH key.", + "example": "My New SSH Key" + }, + "value": { + "type": "string", + "description": "The private key value. This is write-only and will not be returned in the response.", + "example": "-----BEGIN RSA PRIVATE KEY-----\n..." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ssh-key" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/ssh-keys/{ssh_key_id}": { + "get": { + "tags": [ + "ssh-keys" + ], + "summary": "Get an SSH Key", + "description": "Retrieve the details of a single SSH key.", + "parameters": [ + { + "name": "ssh_key_id", + "in": "path", + "required": true, + "description": "The ID of the SSH key.", + "schema": { + "type": "string", + "example": "sshkey-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ssh-key" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "tags": [ + "ssh-keys" + ], + "summary": "Update an SSH Key", + "description": "Update the name of an SSH key.", + "parameters": [ + { + "name": "ssh_key_id", + "in": "path", + "required": true, + "description": "The ID of the SSH key.", + "schema": { + "type": "string", + "example": "sshkey-xxxxxxxxxxxxxxxx" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "ssh-keys" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "The new name for the SSH key.", + "example": "My Updated SSH Key" + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ssh-key" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "tags": [ + "ssh-keys" + ], + "summary": "Delete an SSH Key", + "description": "Delete an SSH key.", + "parameters": [ + { + "name": "ssh_key_id", + "in": "path", + "required": true, + "description": "The ID of the SSH key.", + "schema": { + "type": "string", + "example": "sshkey-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/change-requests": { + "get": { + "operationId": "listWorkspaceChangeRequests", + "summary": "List Change Requests in a Workspace", + "description": "List all change requests for a workspace.", + "tags": [ + "change-requests" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The workspace ID." + }, + { + "in": "query", + "name": "archive", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "When true, returns only archived change requests. When false, returns only unarchived change requests. When omitted, returns all change requests ordered by creation date." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of change requests", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/change-request" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/change-requests/{change_request_id}": { + "get": { + "operationId": "showChangeRequest", + "summary": "Show a Change Request", + "description": "Get details about a specific change request.", + "tags": [ + "change-requests" + ], + "parameters": [ + { + "in": "path", + "name": "change_request_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The change request ID." + } + ], + "responses": { + "200": { + "description": "Change request details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/change-request" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/change-requests/{change_request_id}/actions/archive": { + "get": { + "operationId": "getChangeRequestArchive", + "summary": "Get Change Request Archive Status", + "description": "Get the current state of a change request, including its archive status.", + "tags": [ + "change-requests" + ], + "parameters": [ + { + "in": "path", + "name": "change_request_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The change request ID." + } + ], + "responses": { + "200": { + "description": "Change request details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/change-request" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "archiveChangeRequest", + "summary": "Archive a Change Request", + "description": "Archive a change request to mark it as completed.", + "tags": [ + "change-requests" + ], + "parameters": [ + { + "in": "path", + "name": "change_request_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The change request ID." + } + ], + "responses": { + "200": { + "description": "Change request successfully archived", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/change-request" + } + } + } + } + } + }, + "400": { + "description": "The change request is already archived.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-clients/{oauth_client_id}": { + "get": { + "operationId": "getOAuthClient", + "summary": "Get an OAuth Client", + "description": "Show details of an existing OAuth client.", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "oauth_client_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the OAuth Client." + }, + { + "in": "query", + "name": "show_affected_workspaces", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "If true, includes names of up to 25 affected workspaces and the total count." + } + ], + "responses": { + "200": { + "description": "OAuth Client details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateOAuthClient", + "summary": "Update an OAuth Client", + "description": "Update settings of an existing OAuth client.", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "oauth_client_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the OAuth Client to update." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OAuth Client updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "destroyOAuthClient", + "summary": "Destroy an OAuth Client", + "description": "Remove an existing OAuth client and unlink any associated workspaces.", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "oauth_client_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the OAuth Client to destroy." + } + ], + "responses": { + "204": { + "description": "OAuth Client successfully destroyed." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-clients": { + "post": { + "operationId": "createOAuthClient", + "summary": "Create an OAuth Client", + "description": "Create a VCS connection between an organization and a VCS provider. The organization is specified via the `organization-id` attribute. This endpoint allows you to provide a pre-generated OAuth token string instead of going through the OAuth Application flow.\n", + "tags": [ + "oauth-clients" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "OAuth Client created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/oauth-clients": { + "get": { + "operationId": "listOAuthClients", + "summary": "List OAuth Clients", + "description": "List all VCS connections between an organization and its VCS providers.", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "show_affected_workspaces", + "schema": { + "type": "boolean" + }, + "required": false, + "description": "If true, includes names of up to 25 affected workspaces and total count per client." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of OAuth Clients", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/oauth-client" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createOAuthClientForOrganization", + "summary": "Create an OAuth Client for an Organization", + "description": "Create a VCS connection between an organization and a VCS provider. This endpoint allows you to provide a pre-generated OAuth token string instead of going through the OAuth Application flow.\n", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "OAuth Client created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-client" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-clients/{oauth_client_id}/relationships/projects": { + "post": { + "operationId": "attachOAuthClientToProjects", + "summary": "Attach an OAuth Client to Projects", + "description": "Attach an OAuth client to one or more projects.", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "oauth_client_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the OAuth Client to attach to projects." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "OAuth Client successfully attached to projects." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "detachOAuthClientFromProjects", + "summary": "Detach an OAuth Client from Projects", + "description": "Detach an OAuth client from one or more projects.", + "tags": [ + "oauth-clients" + ], + "parameters": [ + { + "in": "path", + "name": "oauth_client_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the OAuth Client to detach from projects." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "type", + "id" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "id": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "responses": { + "204": { + "description": "OAuth Client successfully detached from projects." + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-tokens/{oauth_token_id}": { + "get": { + "tags": [ + "oauth-tokens" + ], + "summary": "Show an OAuth Token", + "description": "Get details about an OAuth token.", + "operationId": "getOauthToken", + "parameters": [ + { + "name": "oauth_token_id", + "in": "path", + "required": true, + "description": "The ID of the OAuth token.", + "schema": { + "type": "string", + "example": "ot-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-token" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "tags": [ + "oauth-tokens" + ], + "summary": "Update an OAuth Token", + "description": "Update an OAuth token by setting its SSH key.", + "operationId": "updateOauthToken", + "parameters": [ + { + "name": "oauth_token_id", + "in": "path", + "required": true, + "description": "The ID of the OAuth token.", + "schema": { + "type": "string", + "example": "ot-xxxxxxxxxxxxxxxx" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth-tokens" + ] + }, + "attributes": { + "type": "object", + "properties": { + "ssh-key": { + "type": "string", + "nullable": true, + "description": "The SSH private key for the OAuth token. Set to null to remove the key." + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/oauth-token" + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Unprocessable Entity", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "tags": [ + "oauth-tokens" + ], + "summary": "Destroy an OAuth Token", + "description": "Destroy an OAuth token.", + "operationId": "deleteOauthToken", + "parameters": [ + { + "name": "oauth_token_id", + "in": "path", + "required": true, + "description": "The ID of the OAuth token.", + "schema": { + "type": "string", + "example": "ot-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/oauth-tokens": { + "get": { + "tags": [ + "oauth-tokens" + ], + "summary": "List OAuth Tokens for an Organization", + "description": "List all OAuth tokens for a given organization.", + "operationId": "listOauthTokensForOrganization", + "parameters": [ + { + "name": "organization_name", + "in": "path", + "required": true, + "description": "The name of the organization.", + "schema": { + "type": "string", + "example": "my-organization" + } + }, + { + "name": "filter[provider]", + "in": "query", + "required": false, + "description": "Filter tokens by VCS provider name.", + "schema": { + "type": "string", + "example": "github" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/oauth-token" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-clients/{oauth_client_id}/oauth-tokens": { + "get": { + "tags": [ + "oauth-tokens" + ], + "summary": "List OAuth Tokens for an OAuth Client", + "description": "List all OAuth tokens for a given OAuth client.", + "operationId": "listOauthTokensForOauthClient", + "parameters": [ + { + "name": "oauth_client_id", + "in": "path", + "required": true, + "description": "The ID of the OAuth client.", + "schema": { + "type": "string", + "example": "oc-xxxxxxxxxxxxxxxx" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/oauth-token" + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-tokens/{oauth_token_id}/authorized-repos": { + "get": { + "tags": [ + "oauth-tokens" + ], + "summary": "List Authorized Repositories for an OAuth Token", + "description": "List all repositories that the OAuth token is authorized to access.", + "operationId": "listAuthorizedReposForOauthToken", + "parameters": [ + { + "name": "oauth_token_id", + "in": "path", + "required": true, + "description": "The ID of the OAuth token.", + "schema": { + "type": "string", + "example": "ot-xxxxxxxxxxxxxxxx" + } + }, + { + "name": "organization", + "in": "query", + "required": false, + "description": "The VCS organization name to scope repositories to. Required for Azure DevOps providers.", + "schema": { + "type": "string" + } + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/authorized-repo" + } + }, + "meta": { + "type": "object", + "properties": { + "next-page": { + "type": "integer", + "nullable": true, + "description": "The next page number, if more pages are available." + } + } + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/oauth-tokens/{oauth_token_id}/vcs-organizations": { + "get": { + "tags": [ + "oauth-tokens" + ], + "summary": "List VCS Organizations for an OAuth Token", + "description": "List all VCS organizations accessible via the OAuth token. Only applicable to Azure DevOps providers.", + "operationId": "listVcsOrganizationsForOauthToken", + "parameters": [ + { + "name": "oauth_token_id", + "in": "path", + "required": true, + "description": "The ID of the OAuth token.", + "schema": { + "type": "string", + "example": "ot-xxxxxxxxxxxxxxxx" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/vcs-organization" + } + } + } + } + } + } + }, + "404": { + "description": "Not Found", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/github-app-installations": { + "get": { + "operationId": "listGithubAppInstallations", + "summary": "List GitHub App Installations", + "description": "List GitHub App installations available to the current user.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "query", + "name": "filter[name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by GitHub organization or login name." + }, + { + "in": "query", + "name": "filter[installation_id]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by GitHub installation ID." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of GitHub App installations", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/github-app-installation" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/github-app-installations/{github_app_installation_id}/repos": { + "get": { + "operationId": "listGithubAppInstallationRepos", + "summary": "List GitHub App Installation Repositories", + "description": "List repositories accessible through a GitHub App installation.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "path", + "name": "github_app_installation_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the GitHub App installation." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of repositories", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/github-app-repo" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/github-app/installation/{github_app_installation_id}": { + "get": { + "operationId": "getGithubAppInstallation", + "summary": "Show GitHub App Installation", + "description": "Get details about a GitHub App installation.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "path", + "name": "github_app_installation_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the GitHub App installation." + } + ], + "responses": { + "200": { + "description": "GitHub App installation details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/github-app-installation" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/github-app/installations": { + "get": { + "operationId": "listGithubAppInstallationsForCurrentUser", + "summary": "List GitHub App Installations for Current User", + "description": "List GitHub App installations accessible to the current authenticated user.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "query", + "name": "filter[name]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by GitHub organization or login name." + }, + { + "in": "query", + "name": "filter[installation_id]", + "schema": { + "type": "string" + }, + "required": false, + "description": "Filter by GitHub installation ID." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of GitHub App installations", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/github-app-installation" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/github-app-installations": { + "get": { + "operationId": "listOrganizationGithubAppInstallations", + "summary": "List Organization GitHub App Installations", + "description": "List GitHub App installations linked to an organization.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of GitHub App installations", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/github-app-installation" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/github-app-installations/{github_app_installation_id}/repos": { + "get": { + "operationId": "listOrganizationGithubAppInstallationRepos", + "summary": "List Organization GitHub App Installation Repositories", + "description": "List repositories accessible through a GitHub App installation linked to an organization.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "path", + "name": "github_app_installation_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the GitHub App installation." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of repositories", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/github-app-repo" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/github-app-installations/{github_app_installation_id}/link-account": { + "post": { + "operationId": "linkOrganizationGithubAppInstallation", + "summary": "Link GitHub App Installation to Organization", + "description": "Link a GitHub App installation to an organization.", + "tags": [ + "github-app-installations" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "path", + "name": "github_app_installation_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the GitHub App installation." + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/tasks/{id}": { + "get": { + "operationId": "getTask", + "summary": "Get a Run Task", + "description": "Get details about a run task.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run task." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Allows including related resource data. Value must be a comma-separated list containing one or more of `workspace_tasks` or `workspace_tasks.workspace`.\n" + } + ], + "responses": { + "200": { + "description": "Run task details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/task" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateTask", + "summary": "Update a Run Task", + "description": "Update a run task.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run task." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/task" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Run task updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/task" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteTask", + "summary": "Delete a Run Task", + "description": "Delete a run task.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run task." + } + ], + "responses": { + "204": { + "description": "Run task deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/organizations/{organization_name}/tasks": { + "get": { + "operationId": "listOrganizationTasks", + "summary": "List Run Tasks", + "description": "List all run tasks in an organization.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "Allows including related resource data. Value must be a comma-separated list containing one or more of `workspace_tasks` or `workspace_tasks.workspace`.\n" + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of run tasks", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/task" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createTask", + "summary": "Create a Run Task", + "description": "Create a run task in an organization.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "organization_name", + "schema": { + "type": "string" + }, + "required": true, + "description": "The name of the organization." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/task" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Run task created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/task" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/tasks/{id}/relationships/workspace-tasks": { + "get": { + "operationId": "listTaskWorkspaceTasks", + "summary": "List Workspace Run Tasks for a Run Task", + "description": "List all workspace run tasks associated with a run task.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run task." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of workspace run tasks", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace-task" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/tasks": { + "get": { + "operationId": "listWorkspaceTasks", + "summary": "List Workspace Run Tasks", + "description": "List all run tasks associated with a workspace.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of workspace run tasks", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace-task" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "post": { + "operationId": "createWorkspaceTask", + "summary": "Associate a Run Task to a Workspace", + "description": "Associate an existing run task to a workspace.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-task" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "Workspace run task created", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-task" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/workspaces/{workspace_id}/tasks/{id}": { + "get": { + "operationId": "getWorkspaceTask", + "summary": "Show a Workspace Run Task", + "description": "Get details about a workspace run task.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace run task." + } + ], + "responses": { + "200": { + "description": "Workspace run task details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-task" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "patch": { + "operationId": "updateWorkspaceTask", + "summary": "Update a Workspace Run Task", + "description": "Update a workspace run task.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace run task." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-task" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Workspace run task updated", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "$ref": "#/components/schemas/workspace-task" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + }, + "delete": { + "operationId": "deleteWorkspaceTask", + "summary": "Delete a Workspace Run Task", + "description": "Delete a workspace run task, dissociating the run task from the workspace.", + "tags": [ + "run-tasks" + ], + "parameters": [ + { + "in": "path", + "name": "workspace_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace." + }, + { + "in": "path", + "name": "id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the workspace run task." + } + ], + "responses": { + "204": { + "description": "Workspace run task deleted" + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-stages/{task_stage_id}": { + "get": { + "operationId": "getTaskStage", + "summary": "Show a Run Task Stage", + "description": "Get details about a specific run task stage.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "task_stage_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task stage to show." + }, + { + "in": "query", + "name": "include", + "schema": { + "type": "string" + }, + "required": false, + "description": "A comma-separated list of related resources to include. Supported values: run, run.workspace, task-results, policy-evaluations." + } + ], + "responses": { + "200": { + "description": "Task stage details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/task-stage" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-stages/{task_stage_id}/actions/override": { + "post": { + "operationId": "overrideTaskStage", + "summary": "Override a Task Stage", + "description": "Override a task stage that is in the awaiting_override status, allowing the run to continue even when run tasks have failed.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "task_stage_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task stage to override." + } + ], + "responses": { + "200": { + "description": "Task stage successfully overridden", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/task-stage" + } + } + } + } + } + }, + "409": { + "description": "The task stage is not in an overridable state or has no overridable failures.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/runs/{run_id}/task-stages": { + "get": { + "operationId": "listRunTaskStages", + "summary": "List the Run Task Stages in a Run", + "description": "List the run task stages associated with a run.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "run_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the run to list task stages for." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of run task stages", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/task-stage" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-results/{task_result_id}": { + "get": { + "operationId": "getTaskResult", + "summary": "Show a Run Task Result", + "description": "Get details about a specific run task result.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "task_result_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task result to show." + } + ], + "responses": { + "200": { + "description": "Task result details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/task-result" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-results/{task_result_id}/callback": { + "patch": { + "operationId": "callbackTaskResult", + "summary": "Update a Run Task Result", + "description": "Update a run task result with status, message, and optional outcome data. This endpoint is used by run task integrations to report execution results back to HCP Terraform. Requires a url_code query parameter for authentication.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "task_result_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task result to update." + }, + { + "in": "query", + "name": "url_code", + "schema": { + "type": "string" + }, + "required": false, + "description": "The callback authentication token issued to the run task integration. Required for run task integrations; not required for token-authenticated requests." + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "task_results" + ] + }, + "attributes": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "running", + "passed", + "failed" + ], + "description": "The new status for the task result." + }, + "message": { + "type": "string", + "nullable": true, + "description": "A message describing the task execution result." + }, + "url": { + "type": "string", + "nullable": true, + "description": "A URL with details about the task execution." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "outcomes": { + "type": "object", + "properties": { + "data": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "task-result-outcomes" + ] + }, + "attributes": { + "type": "object", + "properties": { + "outcome-id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string", + "nullable": true + }, + "body": { + "type": "string", + "nullable": true + }, + "tags": { + "type": "object", + "nullable": true, + "additionalProperties": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "level": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + }, + "responses": { + "200": { + "description": "Task result updated successfully", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/task-result" + } + } + } + } + } + }, + "409": { + "description": "The task result is in a terminal state and cannot be updated.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "422": { + "description": "Invalid attributes provided.", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-results/{task_result_id}/outcomes": { + "get": { + "operationId": "listTaskResultOutcomes", + "summary": "List the Outcomes for a Run Task Result", + "description": "List the run task result outcomes associated with a run task result.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "task_result_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task result to list outcomes for." + }, + { + "$ref": "#/components/parameters/page_number" + }, + { + "$ref": "#/components/parameters/page_size" + } + ], + "responses": { + "200": { + "description": "List of run task result outcomes", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/task-result-outcome" + } + }, + "meta": { + "type": "object", + "properties": { + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + }, + "/task-result-outcomes/{task_result_outcome_id}": { + "get": { + "operationId": "getTaskResultOutcome", + "summary": "Show a Run Task Result Outcome", + "description": "Get details about a specific run task result outcome.", + "tags": [ + "task-stages" + ], + "parameters": [ + { + "in": "path", + "name": "task_result_outcome_id", + "schema": { + "type": "string" + }, + "required": true, + "description": "The ID of the task result outcome to show." + } + ], + "responses": { + "200": { + "description": "Task result outcome details", + "content": { + "application/vnd.api+json": { + "schema": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/task-result-outcome" + } + } + } + } + } + }, + "default": { + "description": "Error details", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/errors" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer" + } + }, + "schemas": { + "errors": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "title": { + "type": "string" + }, + "detail": { + "type": "string" + } + } + } + } + } + }, + "related": { + "type": "object", + "properties": { + "related": { + "type": "string" + } + } + }, + "links_related": { + "type": "object", + "properties": { + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "self": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + }, + "user": { + "type": "object", + "required": [ + "id", + "type", + "attributes", + "links", + "relationships" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + }, + "attributes": { + "type": "object", + "properties": { + "username": { + "type": "string", + "nullable": true + }, + "is-service-account": { + "description": "Indicates whether this user is a synthetic user representing a team or organization.", + "type": "boolean" + }, + "avatar-url": { + "type": "string", + "nullable": true + }, + "auth-method": { + "type": "string" + }, + "v2-only": { + "type": "boolean" + }, + "is-admin": { + "type": "boolean" + }, + "is-site-admin": { + "description": "Deprecated. Use is-admin.", + "type": "boolean" + }, + "is-sso-login": { + "type": "boolean" + }, + "is-confirmed": { + "type": "boolean" + }, + "is-unified": { + "type": "boolean" + }, + "is-sudo": { + "type": "boolean" + }, + "email": { + "type": "string" + }, + "unconfirmed-email": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string", + "nullable": true + }, + "enterprise-support": { + "type": "boolean" + }, + "has-linked-hcp": { + "type": "boolean" + }, + "has-git-hub-app-token": { + "type": "boolean" + }, + "two-factor": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "verified": { + "type": "boolean" + } + } + }, + "permissions": { + "type": "object", + "properties": { + "can-create-organization": { + "type": "boolean" + }, + "can-view-organizations": { + "type": "boolean" + }, + "can-view-settings": { + "type": "boolean" + }, + "can-view-smtp-settings": { + "type": "boolean" + }, + "can-view-twilio-settings": { + "type": "boolean" + }, + "can-view-saml-settings": { + "type": "boolean" + }, + "can-view-admin-workspaces": { + "type": "boolean" + }, + "can-view-admin-runs": { + "type": "boolean" + }, + "can-view-customization-settings": { + "type": "boolean" + }, + "can-view-cost-estimation-settings": { + "type": "boolean" + }, + "can-view-tool-versions": { + "type": "boolean" + }, + "can-create-tool-versions": { + "type": "boolean" + }, + "can-view-general-settings": { + "type": "boolean" + }, + "can-use-sql-runner": { + "type": "boolean" + }, + "can-view-profile": { + "type": "boolean" + }, + "can-change-email": { + "type": "boolean" + }, + "can-change-username": { + "type": "boolean" + }, + "can-change-password": { + "type": "boolean" + }, + "can-manage-sessions": { + "type": "boolean" + }, + "can-manage-user-tokens": { + "type": "boolean" + }, + "can-update-user": { + "type": "boolean" + }, + "can-reenable-2fa-by-unlinking": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + }, + "can-manage-hcp-accounts": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "authentication-tokens": { + "$ref": "#/components/schemas/links_related" + }, + "github-app-oauth-tokens": { + "$ref": "#/components/schemas/links_related" + }, + "authenticated-resource": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "organizations", + "runs", + "users", + "teams" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "account_update": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "users" + ] + }, + "attributes": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "email": { + "type": "string" + } + } + } + } + } + } + }, + "account_password": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "users" + ] + }, + "attributes": { + "type": "object", + "properties": { + "current_password": { + "type": "string", + "description": "The user's current password. Unlike most API data attributes, this one uses underscore_case instead of kebab-case." + }, + "password": { + "type": "string", + "description": "The user's new password." + }, + "password_confirmation": { + "type": "string", + "description": "The confirmation of the user's new password. Unlike most API data attributes, this one uses underscore_case instead of kebab-case." + } + } + } + } + } + } + }, + "hcp-billing-accounts-id": { + "type": "object", + "nullable": false, + "properties": { + "data": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "hcp-billing-account" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "feature-sets-id": { + "type": "object", + "nullable": true, + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "feature-sets" + ] + } + } + } + } + }, + "hcp-organization": { + "type": "object", + "required": [ + "id", + "type", + "attributes", + "relationships" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "attributes": { + "type": "object", + "required": [ + "name", + "is-hcp-admin" + ], + "properties": { + "name": { + "type": "string" + }, + "hcp-owner-email": { + "type": "string", + "nullable": true + }, + "is-hcp-admin": { + "type": "boolean" + } + } + }, + "relationships": { + "type": "object", + "required": [ + "default-account", + "connected-plans" + ], + "properties": { + "default-account": { + "$ref": "#/components/schemas/hcp-billing-accounts-id" + }, + "connected-plans": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/feature-sets-id" + } + } + } + } + } + } + } + }, + "hcp-billing-account": { + "type": "object", + "required": [ + "id", + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "attributes": { + "type": "object", + "required": [ + "project-id", + "hcp-organization-name", + "hcp-organization-id", + "balance", + "card-brand", + "card-last4", + "card-exp-month", + "card-exp-year", + "account-type", + "status" + ], + "properties": { + "project-id": { + "type": "string" + }, + "hcp-organization-name": { + "type": "string" + }, + "hcp-organization-id": { + "type": "string" + }, + "balance": { + "type": "number" + }, + "card-brand": { + "type": "string" + }, + "card-last4": { + "type": "string" + }, + "card-exp-month": { + "type": "integer" + }, + "card-exp-year": { + "type": "integer" + }, + "account-type": { + "type": "string" + }, + "status": { + "type": "string" + } + } + } + } + }, + "feature-set": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the feature set" + }, + "type": { + "type": "string", + "enum": [ + "feature-sets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "assessments": { + "type": "boolean", + "description": "Whether the feature set includes assessments" + }, + "audit-logging": { + "type": "boolean", + "description": "Whether the feature set includes audit logging" + }, + "can-self-service-downgrade": { + "type": "boolean", + "description": "Whether the organization can self-service downgrade from this feature set" + }, + "change-requests": { + "type": "boolean", + "description": "Whether the feature set includes change requests" + }, + "concurrency-override": { + "type": "boolean", + "description": "Whether concurrency can be overridden for this feature set" + }, + "cost": { + "type": "number", + "description": "The cost of the feature set in cents" + }, + "cost-estimation": { + "type": "boolean", + "description": "Whether the feature set includes cost estimation" + }, + "default-agents-ceiling": { + "type": "number", + "description": "Default maximum number of concurrent agents" + }, + "default-runs-ceiling": { + "type": "number", + "description": "Default maximum number of concurrent runs" + }, + "description": { + "type": "string", + "description": "Description of the feature set" + }, + "global-run-tasks": { + "type": "boolean", + "description": "Whether the feature set includes global run tasks" + }, + "hyok": { + "type": "boolean", + "description": "Whether the feature set includes Hold Your Own Key encryption" + }, + "identifier": { + "type": "string", + "description": "Unique identifier for the feature set" + }, + "terraform-actions": { + "type": "boolean", + "description": "Whether the feature set includes Terraform Actions features" + }, + "is-current": { + "type": "boolean", + "description": "Whether this is a current/active feature set" + }, + "is-free-tier": { + "type": "boolean", + "description": "Whether this is a free tier feature set" + }, + "is-managed-resource-plan": { + "type": "boolean", + "description": "Whether this is a managed resource plan" + }, + "module-deprecations": { + "type": "boolean", + "description": "Whether this feature set includes module deprecations" + }, + "module-revocations": { + "type": "boolean", + "description": "Whether this feature set includes module revocations" + }, + "module-tests-agent-support": { + "type": "boolean" + }, + "module-tests-generation": { + "type": "boolean", + "description": "Whether the feature set includes module test generation" + }, + "name": { + "type": "string", + "description": "Name of the feature set" + }, + "no-code-modules": { + "type": "boolean", + "description": "Whether the feature set includes no-code modules" + }, + "plan": { + "type": "string", + "nullable": true, + "description": "Associated plan ID" + }, + "policy-enforcement": { + "type": "boolean", + "description": "Whether the feature set includes policy enforcement" + }, + "policy-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of policies (null means unlimited)" + }, + "policy-mandatory-enforcement-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of mandatory enforcement policies (null means unlimited)" + }, + "policy-set-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of policy sets (null means unlimited)" + }, + "private-networking": { + "type": "boolean", + "description": "Whether the feature set includes private networking" + }, + "private-policy-agents": { + "type": "boolean", + "description": "Whether the feature set includes private policy agents" + }, + "private-run-tasks": { + "type": "boolean", + "description": "Whether the feature set includes private run tasks" + }, + "private-vcs": { + "type": "boolean", + "description": "Whether the feature set includes private VCS" + }, + "run-task-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of run tasks (null means unlimited)" + }, + "run-task-mandatory-enforcement-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of mandatory enforcement run tasks (null means unlimited)" + }, + "run-task-workspace-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of workspaces per run task (null means unlimited)" + }, + "run-tasks": { + "type": "boolean", + "description": "Whether the feature set includes run tasks" + }, + "self-serve-billing": { + "type": "boolean", + "description": "Whether the feature set supports self-serve billing" + }, + "sentinel": { + "type": "boolean", + "description": "Whether the feature set includes Sentinel (alias for policy-enforcement)" + }, + "sso": { + "type": "boolean", + "description": "Whether the feature set includes SSO" + }, + "stacks": { + "type": "boolean", + "description": "Whether the feature set includes stacks" + }, + "teams": { + "type": "boolean", + "description": "Whether the feature set includes teams" + }, + "user-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of users (null means unlimited)" + }, + "uses-hcp-rum-billing-resource": { + "type": "boolean", + "description": "Whether the feature set uses HCP RUM billing resource" + }, + "versioned-policy-set-limit": { + "type": "number", + "nullable": true, + "description": "Maximum number of versioned policy sets (null means unlimited)" + }, + "waypoint-actions": { + "type": "boolean" + }, + "waypoint-templates-and-addons": { + "type": "boolean" + } + } + } + }, + "required": [ + "id", + "type", + "attributes" + ] + }, + "self-with-pagination": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "first": { + "type": "string" + }, + "prev": { + "type": "string", + "nullable": true + }, + "next": { + "type": "string", + "nullable": true + }, + "last": { + "type": "string" + } + } + }, + "pagination": { + "type": "object", + "properties": { + "current-page": { + "type": "integer" + }, + "page-size": { + "type": "integer" + }, + "prev-page": { + "type": "integer", + "nullable": true + }, + "next-page": { + "type": "integer", + "nullable": true + }, + "total-pages": { + "type": "integer" + }, + "total-count": { + "type": "integer" + } + } + }, + "organizations-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "organizations" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "subscriptions-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "subscriptions" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "subscription": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "subscriptions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "end-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "is-active": { + "type": "boolean" + }, + "start-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "runs-ceiling": { + "type": "integer", + "nullable": true + }, + "agents-ceiling": { + "type": "integer", + "nullable": true + }, + "contract-start-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "contract-user-limit": { + "type": "integer", + "nullable": true + }, + "contract-apply-limit": { + "type": "integer", + "nullable": true + }, + "contract-managed-resources-limit": { + "type": "integer", + "nullable": true + }, + "hcp-organization-id": { + "type": "string", + "nullable": true + }, + "hcp-project-id": { + "type": "string", + "nullable": true + }, + "run-task-limit": { + "type": "integer", + "nullable": true + }, + "run-task-workspace-limit": { + "type": "integer", + "nullable": true + }, + "run-task-mandatory-enforcement-limit": { + "type": "integer", + "nullable": true + }, + "versioned-policy-set-limit": { + "type": "integer", + "nullable": true + }, + "policy-set-limit": { + "type": "integer", + "nullable": true + }, + "policy-limit": { + "type": "integer", + "nullable": true + }, + "policy-mandatory-enforcement-limit": { + "type": "integer", + "nullable": true + }, + "is-public-free-tier": { + "type": "boolean" + }, + "is-self-serve-trial": { + "type": "boolean" + }, + "is-change-approved": { + "type": "boolean" + }, + "free-apply-monthly-limit-starts-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "free-apply-monthly-limit": { + "type": "integer", + "nullable": true + }, + "free-apply-monthly-limit-remaining": { + "type": "integer", + "nullable": true + }, + "free-resource-under-management-monthly-limit": { + "type": "integer", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "required": [ + "organization", + "feature-set" + ], + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "feature-set": { + "$ref": "#/components/schemas/feature-sets-id" + }, + "hcp-billing-account": { + "$ref": "#/components/schemas/links_related" + }, + "next-subscription": { + "$ref": "#/components/schemas/subscriptions-id" + } + } + } + } + }, + "billing-invoice": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The Stripe invoice ID." + }, + "type": { + "type": "string", + "enum": [ + "billing-invoices" + ], + "description": "The resource type identifier." + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "description": "The date the invoice was created." + }, + "external-link": { + "type": "string", + "description": "A link to the Stripe-hosted invoice PDF." + }, + "number": { + "type": "string", + "description": "The invoice number." + }, + "paid": { + "type": "boolean", + "description": "Whether the invoice has been paid." + }, + "status": { + "type": "string", + "description": "The invoice status (e.g., \"paid\", \"draft\")." + }, + "total": { + "type": "integer", + "description": "The total invoice amount in cents." + } + } + } + } + }, + "agent-pool": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "agent-pools" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "organization-scoped": { + "type": "boolean" + }, + "agent-count": { + "type": "integer", + "readOnly": true + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + }, + "relationships": { + "type": "object", + "properties": { + "agents": { + "$ref": "#/components/schemas/links_related" + }, + "authentication-tokens": { + "$ref": "#/components/schemas/links_related" + }, + "workspaces": { + "readOnly": true, + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + }, + "allowed-workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + } + } + } + } + }, + "agent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "agents" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "status": { + "type": "string" + }, + "ip-address": { + "type": "string" + }, + "last-ping-at": { + "type": "string", + "format": "date-time" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + } + } + }, + "agent-pools-id": { + "type": "object", + "nullable": true, + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "nullable": true, + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "agent-pools" + ] + } + } + } + } + }, + "entitlement-sets-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "entitlement-sets" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "projects-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "projects" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "organization": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "organizations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "external-id": { + "type": "string", + "readOnly": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "email": { + "type": "string" + }, + "session-timeout": { + "type": "integer", + "nullable": true + }, + "session-remember": { + "type": "integer", + "nullable": true + }, + "collaborator-auth-policy": { + "type": "string", + "enum": [ + "password", + "two_factor_mandatory" + ] + }, + "plan-expired": { + "type": "boolean", + "readOnly": true + }, + "plan-expires-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true + }, + "plan-is-trial": { + "type": "boolean", + "readOnly": true + }, + "plan-is-enterprise": { + "type": "boolean", + "readOnly": true + }, + "plan-identifier": { + "type": "string", + "readOnly": true + }, + "cost-estimation-enabled": { + "type": "boolean" + }, + "send-passing-statuses-for-untriggered-speculative-plans": { + "type": "boolean" + }, + "aggregated-commit-status-enabled": { + "type": "boolean" + }, + "speculative-plan-management-enabled": { + "type": "boolean" + }, + "allow-force-delete-workspaces": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "hcp-id": { + "type": "string", + "readOnly": true, + "x-vis": [ + "hcpt" + ] + }, + "is-unified": { + "type": "boolean", + "readOnly": true, + "x-vis": [ + "hcpt" + ] + }, + "permissions": { + "type": "object", + "properties": { + "can-update": { + "type": "boolean" + }, + "can-update-authentication-token": { + "type": "boolean" + }, + "can-destroy": { + "type": "boolean" + }, + "can-access-via-teams": { + "type": "boolean" + }, + "can-create-module": { + "type": "boolean" + }, + "can-create-team": { + "type": "boolean" + }, + "can-create-workspace": { + "type": "boolean" + }, + "can-manage-users": { + "type": "boolean" + }, + "can-manage-subscription": { + "type": "boolean" + }, + "can-manage-sso": { + "type": "boolean" + }, + "can-update-oauth": { + "type": "boolean" + }, + "can-update-sentinel": { + "type": "boolean" + }, + "can-update-ssh-keys": { + "type": "boolean" + }, + "can-update-api-token": { + "type": "boolean" + }, + "can-traverse": { + "type": "boolean" + }, + "can-view-usage": { + "type": "boolean" + }, + "can-update-agent-pools": { + "type": "boolean" + }, + "can-manage-tags": { + "type": "boolean" + }, + "can-manage-varsets": { + "type": "boolean" + }, + "can-read-varsets": { + "type": "boolean" + }, + "can-manage-public-providers": { + "type": "boolean" + }, + "can-create-provider": { + "type": "boolean" + }, + "can-manage-public-modules": { + "type": "boolean" + }, + "can-manage-custom-providers": { + "type": "boolean" + }, + "can-manage-run-tasks": { + "type": "boolean" + }, + "can-read-run-tasks": { + "type": "boolean" + }, + "can-create-project": { + "type": "boolean" + }, + "can-enable-stacks": { + "type": "boolean" + }, + "can-manage-org-public-providers": { + "type": "boolean" + }, + "can-manage-org-public-modules": { + "type": "boolean" + }, + "can-manage-assessments": { + "type": "boolean" + }, + "can-read-assessments": { + "type": "boolean" + }, + "can-view-explorer": { + "type": "boolean" + }, + "can-deploy-no-code-modules": { + "type": "boolean" + }, + "can-manage-no-code-modules": { + "type": "boolean" + }, + "can-manage-groups-in-hcp": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + }, + "can-create-project-in-hcp": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + } + } + }, + "fair-run-queuing-enabled": { + "type": "boolean", + "readOnly": true + }, + "saml-enabled": { + "type": "boolean" + }, + "owners-team-saml-role-id": { + "type": "string", + "nullable": true + }, + "two-factor-conformant": { + "type": "boolean" + }, + "assessments-enforced": { + "type": "boolean" + }, + "is-in-degraded-mode": { + "type": "boolean", + "readOnly": true + }, + "remaining-testable-count": { + "type": "integer", + "readOnly": true + }, + "stacks-enabled": { + "type": "boolean", + "x-vis": [ + "public-beta" + ] + }, + "over-stacks-resource-limit": { + "type": "boolean", + "readOnly": true, + "x-vis": [ + "public-beta" + ] + }, + "default-execution-mode": { + "type": "string", + "enum": [ + "remote", + "local", + "agent" + ] + }, + "test-generation-enabled": { + "type": "boolean", + "readOnly": true, + "x-vis": [ + "public-beta" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + }, + "relationships": { + "type": "object", + "properties": { + "default-agent-pool": { + "$ref": "#/components/schemas/agent-pools-id" + }, + "oauth-tokens": { + "$ref": "#/components/schemas/links_related" + }, + "authentication-token": { + "$ref": "#/components/schemas/links_related" + }, + "audit-trails-authentication-token": { + "$ref": "#/components/schemas/links_related", + "x-vis": [ + "hcpt" + ] + }, + "entitlement-set": { + "$ref": "#/components/schemas/entitlement-sets-id" + }, + "subscription": { + "$ref": "#/components/schemas/subscriptions-id" + }, + "default-project": { + "$ref": "#/components/schemas/projects-id" + } + } + } + } + }, + "status-counts": { + "type": "object", + "properties": { + "total": { + "type": "integer" + }, + "active": { + "type": "integer" + }, + "invited": { + "type": "integer" + } + } + }, + "organization-membership": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true, + "description": "The organization membership ID" + }, + "type": { + "type": "string", + "enum": [ + "organization-memberships" + ] + }, + "attributes": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "type": "string", + "enum": [ + "active", + "invited" + ], + "description": "The status of the organization membership. Can be \"active\" or \"invited\"." + }, + "email": { + "type": "string", + "format": "email", + "description": "The email address of the user." + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true, + "description": "The timestamp when the organization membership was created." + }, + "is-org-two-factor-required": { + "type": "boolean", + "nullable": true, + "description": "Whether two-factor authentication is required for the organization. Only present for invited users." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "teams": { + "type": "object", + "description": "The teams this user is a member of. Only shows teams the requesting user has access to, and teams that are not \"secret\" (unless the requester is a member).", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "teams" + ] + } + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "user": { + "type": "object", + "description": "The user associated with this organization membership.", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "organization": { + "type": "object", + "description": "The organization this membership belongs to.", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "organizations" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self-with-pagination" + }, + "meta": { + "type": "object", + "properties": { + "status-counts": { + "$ref": "#/components/schemas/status-counts" + }, + "pagination": { + "$ref": "#/components/schemas/pagination" + } + } + } + } + }, + "team": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "teams" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the team, which can only include letters, numbers, `-`, and `_`." + }, + "users-count": { + "type": "integer", + "readOnly": true, + "description": "The number of active users in the team." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Team description. Only available when effective permissions are enabled for unified organizations." + }, + "sso-team-id": { + "type": "string", + "nullable": true, + "description": "The unique identifier of the team from the SAML MemberOf attribute." + }, + "visibility": { + "type": "string", + "enum": [ + "secret", + "organization" + ], + "description": "The team's visibility. Can be \"secret\" or \"organization\" (visible)." + }, + "allow-member-token-management": { + "type": "boolean", + "description": "Whether team members are allowed to manage their own authentication tokens." + }, + "hcp-resource-name": { + "type": "string", + "nullable": true, + "readOnly": true, + "description": "The HCP resource name for unified teams.", + "x-vis": [ + "hcpt" + ] + }, + "is-unified": { + "type": "boolean", + "readOnly": true, + "description": "Whether this team is unified with HCP.", + "x-vis": [ + "hcpt" + ] + }, + "non-service-users-count": { + "type": "integer", + "nullable": true, + "readOnly": true, + "description": "The number of non-service account users in the team." + }, + "permissions": { + "type": "object", + "readOnly": true, + "description": "Permissions for the current user on this team.", + "properties": { + "can-update-membership": { + "type": "boolean" + }, + "can-destroy": { + "type": "boolean" + }, + "can-update-organization-access": { + "type": "boolean" + }, + "can-update-api-token": { + "type": "boolean" + }, + "can-update-visibility": { + "type": "boolean" + }, + "can-update-name": { + "type": "boolean" + }, + "can-update-sso-team-id": { + "type": "boolean" + }, + "can-update-member-token-management": { + "type": "boolean" + }, + "can-view-api-token": { + "type": "boolean" + } + } + }, + "organization-access": { + "type": "object", + "nullable": true, + "description": "Settings for the team's organization-level permissions.", + "properties": { + "manage-policies": { + "type": "boolean" + }, + "manage-workspaces": { + "type": "boolean" + }, + "manage-vcs-settings": { + "type": "boolean" + }, + "manage-policy-overrides": { + "type": "boolean" + }, + "manage-modules": { + "type": "boolean" + }, + "manage-providers": { + "type": "boolean" + }, + "manage-run-tasks": { + "type": "boolean" + }, + "manage-projects": { + "type": "boolean" + }, + "manage-membership": { + "type": "boolean" + }, + "manage-teams": { + "type": "boolean" + }, + "manage-organization-access": { + "type": "boolean" + }, + "access-secret-teams": { + "type": "boolean" + }, + "read-projects": { + "type": "boolean" + }, + "read-workspaces": { + "type": "boolean" + }, + "manage-agent-pools": { + "type": "boolean" + }, + "manage-public-providers": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + }, + "manage-public-modules": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + }, + "manage-registry-components": { + "type": "boolean", + "nullable": true + }, + "manage-registry-artifact-tags": { + "type": "boolean", + "nullable": true + }, + "manage-registry-artifact-version-tags": { + "type": "boolean", + "nullable": true + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "users": { + "type": "object", + "description": "Team members (active users only).", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + } + }, + "links": { + "$ref": "#/components/schemas/links_related" + } + } + }, + "organization-memberships": { + "type": "object", + "description": "Organization memberships for team members.", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "organization-memberships" + ] + } + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "authentication-token": { + "$ref": "#/components/schemas/links_related" + }, + "authentication-tokens": { + "$ref": "#/components/schemas/links_related" + } + } + } + } + }, + "effective-tag-bindings-id": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "object", + "nullable": true, + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "effective-tag-bindings" + ] + } + } + } + } + }, + "project": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "projects" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + }, + "permissions": { + "type": "object", + "nullable": true, + "properties": { + "can-read": { + "type": "boolean" + }, + "can-update": { + "type": "boolean" + }, + "can-destroy": { + "type": "boolean" + }, + "can-create-workspace": { + "type": "boolean" + }, + "can-move-workspace": { + "type": "boolean" + }, + "can-move-stack": { + "type": "boolean" + }, + "can-manage-stacks": { + "type": "boolean" + }, + "can-view-stacks": { + "type": "boolean" + }, + "can-update-stacks": { + "type": "boolean" + }, + "can-deploy-no-code-modules": { + "type": "boolean" + }, + "can-read-teams": { + "type": "boolean" + }, + "can-manage-tags": { + "type": "boolean" + }, + "can-manage-teams": { + "type": "boolean" + }, + "can-manage-in-hcp": { + "type": "boolean", + "x-vis": [ + "hcpt" + ] + }, + "can-manage-varsets": { + "type": "boolean" + }, + "can-manage-ephemeral-workspace-for-projects": { + "type": "boolean" + } + } + }, + "workspace-count": { + "type": "integer", + "nullable": true + }, + "team-count": { + "type": "integer", + "nullable": true + }, + "hcp-id": { + "type": "string", + "nullable": true, + "x-vis": [ + "hcpt" + ] + }, + "is-unified": { + "type": "boolean", + "nullable": true, + "x-vis": [ + "hcpt" + ] + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/organizations-id" + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string" + } + } + } + } + }, + "tag-bindings": { + "type": "object", + "nullable": true, + "properties": { + "links": { + "type": "object", + "properties": { + "related": { + "type": "string" + } + } + } + } + }, + "effective-tag-bindings": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "$ref": "#/components/schemas/effective-tag-bindings-id" + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string" + } + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "token-ttl-policy": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true, + "description": "The token TTL policy ID" + }, + "type": { + "type": "string", + "enum": [ + "organization-token-ttl-policies" + ] + }, + "attributes": { + "type": "object", + "properties": { + "token-type": { + "type": "string", + "description": "The type of the token TTL policy", + "enum": [ + "organization", + "team", + "user", + "audit_trails" + ], + "example": "organization" + }, + "max-ttl-ms": { + "type": "integer", + "description": "The maximum time-to-live for the token in milliseconds", + "example": 3600000 + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "When the policy was created" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "description": "When the policy was last updated" + } + }, + "required": [ + "token-type", + "max-ttl-ms" + ] + } + } + }, + "tag-binding": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true, + "example": "tb-7AHdkTVXrmxiB8vQ" + }, + "type": { + "type": "string", + "readOnly": true, + "enum": [ + "tag-bindings" + ] + }, + "attributes": { + "type": "object", + "required": [ + "key" + ], + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + }, + "tag-bindings-request": { + "x-helperify": { + "jsonapitype": "tag-bindings" + }, + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/tag-binding" + } + } + } + }, + "runs-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "runs" + ] + } + } + } + } + }, + "vars-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + } + } + } + } + }, + "workspace": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + }, + "attributes": { + "type": "object", + "properties": { + "allow-destroy-plan": { + "type": "boolean" + }, + "auto-apply": { + "type": "boolean" + }, + "auto-apply-run-trigger": { + "type": "boolean" + }, + "auto-destroy-activity-duration": { + "type": "string", + "nullable": true + }, + "auto-destroy-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "auto-destroy-status": { + "type": "string", + "nullable": true + }, + "inherits-project-auto-destroy": { + "type": "boolean" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "environment": { + "type": "string" + }, + "locked": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "queue-all-runs": { + "type": "boolean" + }, + "speculative-enabled": { + "type": "boolean" + }, + "structured-run-output-enabled": { + "type": "boolean" + }, + "terraform-version": { + "type": "string" + }, + "working-directory": { + "type": "string", + "nullable": true + }, + "global-remote-state": { + "type": "boolean" + }, + "project-remote-state": { + "type": "boolean" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "resource-count": { + "type": "integer" + }, + "apply-duration-average": { + "type": "integer", + "nullable": true + }, + "plan-duration-average": { + "type": "integer", + "nullable": true + }, + "policy-check-failures": { + "type": "integer", + "nullable": true + }, + "run-failures": { + "type": "integer", + "nullable": true + }, + "workspace-kpis-runs-count": { + "type": "integer", + "nullable": true + }, + "latest-change-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "operations": { + "type": "boolean", + "description": "Deprecated. Use execution-mode instead." + }, + "execution-mode": { + "type": "string", + "enum": [ + "remote", + "local", + "agent" + ] + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "identifier": { + "type": "string" + }, + "display-identifier": { + "type": "string", + "nullable": true + }, + "branch": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "github-app-installation-id": { + "type": "string", + "nullable": true + }, + "tags-regex": { + "type": "string", + "nullable": true + } + } + }, + "vcs-repo-identifier": { + "type": "string", + "nullable": true + }, + "permissions": { + "type": "object", + "nullable": true, + "properties": { + "can-update": { + "type": "boolean" + }, + "can-destroy": { + "type": "boolean" + }, + "can-queue-run": { + "type": "boolean" + }, + "can-read-run": { + "type": "boolean" + }, + "can-read-variable": { + "type": "boolean" + }, + "can-update-variable": { + "type": "boolean" + }, + "can-read-state-versions": { + "type": "boolean" + }, + "can-read-state-outputs": { + "type": "boolean" + }, + "can-create-state-versions": { + "type": "boolean" + }, + "can-queue-apply": { + "type": "boolean" + }, + "can-lock": { + "type": "boolean" + }, + "can-unlock": { + "type": "boolean" + }, + "can-force-unlock": { + "type": "boolean" + }, + "can-read-settings": { + "type": "boolean" + }, + "can-manage-tags": { + "type": "boolean" + }, + "can-manage-run-tasks": { + "type": "boolean" + }, + "can-force-delete": { + "type": "boolean" + }, + "can-manage-assessments": { + "type": "boolean" + }, + "can-manage-ephemeral-workspaces": { + "type": "boolean" + }, + "can-read-assessment-results": { + "type": "boolean" + }, + "can-queue-destroy": { + "type": "boolean" + } + } + }, + "actions": { + "type": "object", + "properties": { + "is-destroyable": { + "type": "boolean" + } + } + }, + "description": { + "type": "string", + "nullable": true + }, + "file-triggers-enabled": { + "type": "boolean" + }, + "trigger-prefixes": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "trigger-patterns": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "assessments-enabled": { + "type": "boolean" + }, + "last-assessment-result-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "locked-reason": { + "type": "string", + "nullable": true + }, + "source": { + "type": "string", + "nullable": true + }, + "source-name": { + "type": "string", + "nullable": true + }, + "source-url": { + "type": "string", + "nullable": true + }, + "tag-names": { + "type": "array", + "items": { + "type": "string" + } + }, + "setting-overwrites": { + "type": "object", + "properties": { + "execution-mode": { + "type": "boolean" + }, + "agent-pool": { + "type": "boolean" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "ssh-key": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ssh-keys" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "locked-by": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users", + "teams", + "runs" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "current-run": { + "$ref": "#/components/schemas/runs-id" + }, + "latest-run": { + "$ref": "#/components/schemas/runs-id" + }, + "outputs": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspace-outputs" + ] + } + } + } + } + } + }, + "remote-state-consumers": { + "type": "object", + "properties": { + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "current-state-version": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + } + } + } + } + }, + "current-configuration-version": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "configuration-versions" + ] + } + } + } + } + }, + "agent-pool": { + "$ref": "#/components/schemas/agent-pools-id" + }, + "readme": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "readmes" + ] + } + } + } + } + }, + "project": { + "$ref": "#/components/schemas/projects-id" + }, + "current-assessment-result": { + "type": "object", + "nullable": true, + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "assessment-results" + ] + } + } + } + } + }, + "vars": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/vars-id" + } + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "notification-configuration": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "notification-configurations" + ] + }, + "attributes": { + "type": "object", + "required": [ + "name", + "destination-type", + "enabled" + ], + "properties": { + "name": { + "type": "string", + "description": "The name of the notification configuration." + }, + "destination-type": { + "type": "string", + "description": "The type of notification destination (e.g., email, slack, generic, microsoft-teams).", + "enum": [ + "email", + "slack", + "generic", + "microsoft-teams" + ] + }, + "enabled": { + "type": "boolean", + "description": "Whether the notification configuration is enabled." + }, + "triggers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "List of trigger events for this notification." + }, + "url": { + "type": "string", + "nullable": true, + "description": "The webhook URL for non-email destinations." + }, + "token": { + "type": "string", + "nullable": true, + "writeOnly": true, + "description": "The authentication token for the webhook." + }, + "email-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "description": "Email addresses for email-type notifications." + }, + "user-email-addresses": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "readOnly": true, + "description": "Email addresses of users associated with this notification." + }, + "delivery-responses": { + "type": "array", + "items": { + "type": "object" + }, + "readOnly": true, + "description": "Responses from notification delivery attempts." + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "subscribable": { + "type": "object", + "description": "The resource (workspace, project, or team) this notification is configured for.", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces", + "projects", + "teams" + ] + } + } + } + } + }, + "users": { + "type": "object", + "description": "Users associated with this notification (for email type).", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + } + } + } + } + } + } + } + }, + "workspaces-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "users-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "configuration-versions-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "configuration-versions" + ] + } + } + } + } + }, + "query": { + "type": "object", + "required": [ + "type", + "attributes", + "relationships" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "queries" + ] + }, + "attributes": { + "type": "object", + "properties": { + "actions": { + "type": "object", + "required": [ + "is-cancelable", + "is-force-cancelable" + ], + "properties": { + "is-cancelable": { + "type": "boolean" + }, + "is-force-cancelable": { + "type": "boolean" + } + } + }, + "canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "source": { + "type": "string" + }, + "status-timestamps": { + "type": "object", + "properties": { + "pending-at": { + "type": "string", + "format": "date-time" + }, + "queued-at": { + "type": "string", + "format": "date-time" + }, + "errored-at": { + "type": "string", + "format": "date-time" + }, + "canceled-at": { + "type": "string", + "format": "date-time" + }, + "running-at": { + "type": "string", + "format": "date-time" + }, + "finished-at": { + "type": "string", + "format": "date-time" + } + } + }, + "status": { + "type": "string", + "enum": [ + "pending", + "running", + "finished", + "canceled", + "errored" + ] + }, + "log-read-url": { + "type": "string", + "readOnly": true + }, + "permissions": { + "type": "object", + "properties": { + "can-cancel": { + "type": "boolean" + }, + "can-force-cancel": { + "type": "boolean" + } + } + }, + "force-cancel-available-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "required": [ + "workspace", + "configuration-version" + ], + "properties": { + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + }, + "canceled-by": { + "$ref": "#/components/schemas/users-id" + }, + "configuration-version": { + "$ref": "#/components/schemas/configuration-versions-id" + }, + "created-by": { + "$ref": "#/components/schemas/users-id" + } + } + } + } + }, + "var": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "sensitive": { + "type": "boolean" + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env", + "terraform-cloud", + "policy-set" + ] + }, + "hcl": { + "type": "boolean" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "description": { + "type": "string", + "nullable": true + }, + "version-id": { + "type": "string" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "varset": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "varsets" + ] + } + } + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "overwritten": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/vars-id" + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "workspace-var": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + }, + "attributes": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string", + "nullable": true + }, + "sensitive": { + "type": "boolean" + }, + "category": { + "type": "string", + "enum": [ + "terraform", + "env", + "terraform-cloud" + ] + }, + "hcl": { + "type": "boolean" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "description": { + "type": "string", + "nullable": true + }, + "version-id": { + "type": "string" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "configurable": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + }, + "workspace": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + }, + "overwritten": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + } + } + } + } + } + }, + "overwriter": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + } + } + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string", + "format": "uri" + } + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "varset": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "varsets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "global": { + "type": "boolean" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "var-count": { + "type": "integer", + "readOnly": true + }, + "workspace-count": { + "type": "integer", + "readOnly": true + }, + "project-count": { + "type": "integer", + "readOnly": true + }, + "stack-count": { + "type": "integer", + "readOnly": true + }, + "priority": { + "type": "boolean" + }, + "permissions": { + "type": "object", + "readOnly": true, + "properties": { + "can-update": { + "type": "boolean" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "organizations" + ] + } + } + } + } + }, + "vars": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "vars" + ] + } + } + } + } + } + }, + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "projects" + ] + } + } + } + } + } + }, + "stacks": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "stacks" + ] + } + } + } + } + } + }, + "parent": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "organizations", + "projects" + ] + } + } + } + } + } + } + } + } + }, + "workspace-resource": { + "type": "object", + "required": [ + "id", + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true, + "description": "The ID of the workspace resource" + }, + "type": { + "type": "string", + "enum": [ + "resources" + ] + }, + "attributes": { + "type": "object", + "properties": { + "address": { + "type": "string", + "description": "The full address of the resource in Terraform configuration" + }, + "name": { + "type": "string", + "description": "The name of the resource" + }, + "created-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true, + "description": "The timestamp when the resource was first created" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true, + "description": "The timestamp when the resource was last updated" + }, + "module": { + "type": "string", + "nullable": true, + "description": "The module name where the resource is defined (e.g., \"root\" for root module)" + }, + "provider": { + "type": "string", + "nullable": true, + "description": "The provider name (e.g., \"hashicorp/random\")" + }, + "provider-type": { + "type": "string", + "nullable": true, + "description": "The resource type from the provider (e.g., \"random_pet\")" + }, + "modified-by-state-version-id": { + "type": "string", + "nullable": true, + "readOnly": true, + "description": "The ID of the state version that last modified this resource" + }, + "name-index": { + "type": "string", + "nullable": true, + "description": "The index of the resource when there are multiple instances with the same name" + } + } + } + } + }, + "applies-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "applies" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "cost-estimates-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "cost-estimates" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "plans-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "plans" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "run-events-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "run-events" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "task-stages-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "task-stages" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "policy-checks-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policy-checks" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "comments-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspace-comments" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "run": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "runs" + ] + }, + "attributes": { + "type": "object", + "properties": { + "actions": { + "type": "object", + "properties": { + "is-cancelable": { + "type": "boolean" + }, + "is-confirmable": { + "type": "boolean" + }, + "is-discardable": { + "type": "boolean" + }, + "is-force-cancelable": { + "type": "boolean" + } + } + }, + "allow-config-generation": { + "type": "boolean" + }, + "allow-empty-apply": { + "type": "boolean" + }, + "auto-apply": { + "type": "boolean" + }, + "comment": { + "type": "string", + "writeOnly": true + }, + "canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "has-changes": { + "type": "boolean" + }, + "is-destroy": { + "type": "boolean" + }, + "message": { + "type": "string" + }, + "plan-only": { + "type": "boolean" + }, + "refresh": { + "type": "boolean" + }, + "refresh-only": { + "type": "boolean" + }, + "replace-addrs": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "save-plan": { + "type": "boolean" + }, + "source": { + "type": "string" + }, + "status-timestamps": { + "type": "object", + "properties": { + "fetching-at": { + "type": "string", + "format": "date-time" + }, + "fetched-at": { + "type": "string", + "format": "date-time" + }, + "pre-plan-running-at": { + "type": "string", + "format": "date-time" + }, + "pre-plan-completed-at": { + "type": "string", + "format": "date-time" + }, + "plan-queued-at": { + "type": "string", + "format": "date-time" + }, + "planning-at": { + "type": "string", + "format": "date-time" + }, + "planned-at": { + "type": "string", + "format": "date-time" + }, + "post-plan-running-at": { + "type": "string", + "format": "date-time" + }, + "post-plan-completed-at": { + "type": "string", + "format": "date-time" + }, + "cost-estimating-at": { + "type": "string", + "format": "date-time" + }, + "cost-estimated-at": { + "type": "string", + "format": "date-time" + }, + "policy-soft-failed-at": { + "type": "string", + "format": "date-time" + }, + "policy-checked-at": { + "type": "string", + "format": "date-time" + }, + "confirmed-at": { + "type": "string", + "format": "date-time" + }, + "planned-and-finished-at": { + "type": "string", + "format": "date-time" + }, + "planned-and-saved-at": { + "type": "string", + "format": "date-time" + }, + "pre-apply-running-at": { + "type": "string", + "format": "date-time" + }, + "pre-apply-completed-at": { + "type": "string", + "format": "date-time" + }, + "apply-queued-at": { + "type": "string", + "format": "date-time" + }, + "applying-at": { + "type": "string", + "format": "date-time" + }, + "post-apply-completed-at": { + "type": "string", + "format": "date-time" + }, + "applied-at": { + "type": "string", + "format": "date-time" + }, + "post-apply-running-at": { + "type": "string", + "format": "date-time" + }, + "discarded-at": { + "type": "string", + "format": "date-time" + }, + "errored-at": { + "type": "string", + "format": "date-time" + }, + "canceled-at": { + "type": "string", + "format": "date-time" + }, + "force-canceled-at": { + "type": "string", + "format": "date-time" + }, + "assessed-at": { + "type": "string", + "format": "date-time" + }, + "queuing-at": { + "type": "string", + "format": "date-time" + }, + "queuing-apply-at": { + "type": "string", + "format": "date-time" + } + } + }, + "status": { + "type": "string", + "enum": [ + "pending", + "fetching", + "fetching_completed", + "pre_plan_running", + "pre_plan_completed", + "queuing", + "plan_queued", + "planning", + "planned", + "post_plan_running", + "post_plan_completed", + "cost_estimating", + "cost_estimated", + "policy_checking", + "policy_override", + "policy_soft_failed", + "policy_checked", + "confirmed", + "pre_apply_running", + "pre_apply_completed", + "queuing_apply", + "apply_queued", + "applying", + "post_apply_running", + "post_apply_completed", + "applied", + "discarded", + "errored", + "canceled", + "planned_and_finished", + "planned_and_saved", + "assessing", + "assessed" + ] + }, + "target-addrs": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "trigger-reason": { + "type": "string" + }, + "terraform-version": { + "type": "string" + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "triggering-source-name": { + "type": "string", + "nullable": true + }, + "policy-paths": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "invoke-action-addrs": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true + }, + "permissions": { + "type": "object", + "properties": { + "can-apply": { + "type": "boolean" + }, + "can-cancel": { + "type": "boolean" + }, + "can-comment": { + "type": "boolean" + }, + "can-discard": { + "type": "boolean" + }, + "can-force-execute": { + "type": "boolean" + }, + "can-force-cancel": { + "type": "boolean" + }, + "can-override-policy-check": { + "type": "boolean" + } + } + }, + "variables": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + }, + "force-cancel-available-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + }, + "triggering-source": { + "$ref": "#/components/schemas/workspaces-id" + }, + "triggering-run": { + "$ref": "#/components/schemas/runs-id" + }, + "apply": { + "$ref": "#/components/schemas/applies-id" + }, + "canceled-by": { + "$ref": "#/components/schemas/users-id" + }, + "configuration-version": { + "$ref": "#/components/schemas/configuration-versions-id" + }, + "confirmed-by": { + "$ref": "#/components/schemas/users-id" + }, + "cost-estimate": { + "$ref": "#/components/schemas/cost-estimates-id" + }, + "created-by": { + "$ref": "#/components/schemas/users-id" + }, + "plan": { + "$ref": "#/components/schemas/plans-id" + }, + "run-events": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/run-events-id" + } + } + } + }, + "task-stages": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/task-stages-id" + } + } + } + }, + "policy-checks": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-checks-id" + } + } + } + }, + "run-trigger-snapshots": { + "$ref": "#/components/schemas/related" + }, + "comments": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/comments-id" + } + } + } + } + } + } + } + }, + "ingress-attributes-id": { + "type": "object", + "properties": { + "data": { + "nullable": true, + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "ingress-attributes" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "configuration-version": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "configuration-versions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "auto-queue-runs": { + "type": "boolean" + }, + "error": { + "type": "string", + "nullable": true + }, + "error-message": { + "type": "string", + "nullable": true + }, + "source": { + "type": "string", + "nullable": true + }, + "speculative": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "fetching", + "uploaded", + "archived", + "errored", + "backing_data_soft_deleted", + "backing_data_permanently_deleted" + ] + }, + "status-timestamps": { + "type": "object", + "properties": { + "fetching-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "uploaded-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "errored-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "archived-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "soft-delete-backing-data-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "restore-backing-data-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "permanently-delete-backing-data-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "provisional": { + "type": "boolean" + }, + "upload-url": { + "type": "string", + "nullable": true, + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "ingress-attributes": { + "$ref": "#/components/schemas/ingress-attributes-id" + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "download": { + "type": "string" + } + } + } + } + }, + "workspace-comment": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "comments" + ] + }, + "attributes": { + "type": "object", + "properties": { + "body": { + "type": "string" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "run-event": { + "$ref": "#/components/schemas/run-events-id" + } + } + } + } + }, + "run-trigger": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "run-triggers" + ] + }, + "attributes": { + "type": "object", + "properties": { + "workspace-name": { + "type": "string" + }, + "sourceable-name": { + "type": "string" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + }, + "sourceable": { + "$ref": "#/components/schemas/workspaces-id" + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "pagination-without-totals": { + "type": "object", + "properties": { + "current-page": { + "type": "integer" + }, + "page-size": { + "type": "integer" + }, + "prev-page": { + "type": "integer", + "nullable": true + }, + "next-page": { + "type": "integer", + "nullable": true + } + } + }, + "plan": { + "type": "object", + "required": [ + "id", + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "example": "plan-8F5JFydVYAmtTjET" + }, + "type": { + "type": "string", + "enum": [ + "plans" + ] + }, + "attributes": { + "type": "object", + "properties": { + "execution-details": { + "type": "object", + "nullable": true, + "description": "Details about the execution of this plan. Null if plan has not started.", + "properties": { + "mode": { + "type": "string", + "description": "Execution mode of the run", + "enum": [ + "remote", + "agent", + "local" + ] + }, + "agent-id": { + "type": "string", + "example": "agent-S1Y7tcKxXPJDQAvq", + "description": "ID of the agent used for this run (when mode is agent)", + "x-vis": [ + "hcpt" + ] + }, + "agent-name": { + "type": "string", + "example": "agent_01", + "description": "Name of the agent used for this run (when mode is agent)", + "x-vis": [ + "hcpt" + ] + }, + "agent-pool-id": { + "type": "string", + "example": "apool-Zigq2VGreKq7nwph", + "description": "ID of the agent pool used for this run (when mode is agent)", + "x-vis": [ + "hcpt" + ] + }, + "agent-pool-name": { + "type": "string", + "example": "first-pool", + "description": "Name of the agent pool used for this run (when mode is agent)", + "x-vis": [ + "hcpt" + ] + } + } + }, + "generated-configuration": { + "type": "boolean", + "default": false, + "nullable": true, + "description": "Whether the plan generated new configuration as part of this run" + }, + "has-changes": { + "type": "boolean", + "description": "Whether the plan has any changes" + }, + "resource-additions": { + "type": "integer", + "description": "Number of resources that will be added", + "nullable": true + }, + "resource-changes": { + "type": "integer", + "description": "Number of resources that will be changed", + "nullable": true + }, + "resource-destructions": { + "type": "integer", + "description": "Number of resources that will be destroyed", + "nullable": true + }, + "resource-imports": { + "type": "integer", + "description": "Number of resources that will be imported", + "nullable": true + }, + "structured-run-output-enabled": { + "type": "boolean", + "nullable": true, + "description": "Whether structured run output is enabled" + }, + "status": { + "type": "string", + "description": "Current status of the plan", + "enum": [ + "pending", + "managed_queued", + "queued", + "running", + "errored", + "canceled", + "finished", + "unreachable" + ] + }, + "status-timestamps": { + "type": "object", + "description": "Timestamps for state transitions of the plan", + "properties": { + "queued-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "pending-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "started-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "finished-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "log-read-url": { + "type": "string", + "nullable": true, + "description": "URL to read the logs for this plan" + }, + "actions": { + "type": "object", + "description": "Actions available for this plan", + "properties": { + "is-exportable": { + "type": "boolean", + "description": "Whether the plan can be exported" + } + } + }, + "permissions": { + "type": "object", + "description": "Permissions for the current user related to this plan", + "nullable": true, + "properties": { + "can-export": { + "type": "boolean", + "description": "Whether the current user can export the plan" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "state-versions": { + "type": "object", + "description": "State versions associated with this plan (for TF <= 0.8)", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + } + } + } + } + } + }, + "exports": { + "type": "object", + "description": "Exports associated with this plan", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "plan-exports" + ] + } + } + } + } + } + }, + "hyok-encrypted-data-key": { + "type": "object", + "description": "HYOK encrypted data key associated with this plan", + "nullable": true, + "x-vis": [ + "public-beta" + ], + "properties": { + "data": { + "type": "object", + "nullable": true, + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "hyok-encrypted-data-keys" + ] + } + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "format": "uri", + "description": "API URL for this plan" + }, + "json-output": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the JSON formatted execution plan (available for Terraform 0.12+)" + }, + "json-output-redacted": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the redacted JSON formatted execution plan (available for Terraform 0.15.2+)" + }, + "json-schema": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the JSON schema of this plan (available for Terraform 0.12+)" + }, + "sanitized-plan": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the sanitized plan (available when HYOK is enabled and with compatible Terraform version)", + "x-vis": [ + "public-beta" + ] + } + } + } + } + }, + "policy-sets-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policy-sets" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "policy": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "policies" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the policy." + }, + "description": { + "type": "string", + "nullable": true, + "description": "Text describing the policy's purpose. Supports Markdown." + }, + "kind": { + "type": "string", + "enum": [ + "sentinel", + "opa" + ], + "description": "The policy-as-code framework for the policy." + }, + "query": { + "type": "string", + "nullable": true, + "description": "The OPA query to run. Only present for OPA policies." + }, + "enforcement-level": { + "type": "string", + "enum": [ + "hard-mandatory", + "soft-mandatory", + "advisory", + "mandatory" + ], + "description": "The enforcement level of the policy. For Sentinel, valid values are hard-mandatory, soft-mandatory, and advisory. For OPA, valid values are mandatory and advisory." + }, + "enforce": { + "type": "array", + "description": "DEPRECATED: Use enforcement-level instead. An array of enforcement configurations mapping policy file paths to their enforcement modes.", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "mode": { + "type": "string" + } + } + } + }, + "policy-set-count": { + "type": "integer", + "readOnly": true, + "description": "The number of policy sets that include this policy." + }, + "updated-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true, + "description": "The time of the most recent policy code upload." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "policy-sets": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-sets-id" + } + } + } + } + } + } + } + }, + "policy-check": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "policy-checks" + ] + }, + "attributes": { + "type": "object", + "properties": { + "result": { + "type": "object", + "nullable": true, + "description": "The result of the policy evaluation. Null until the policy check completes. The `sentinel` key contains low-level Sentinel details and its structure may change over time.", + "properties": { + "result": { + "type": "boolean" + }, + "passed": { + "type": "integer" + }, + "total-failed": { + "type": "integer" + }, + "hard-failed": { + "type": "integer" + }, + "soft-failed": { + "type": "integer" + }, + "advisory-failed": { + "type": "integer" + }, + "duration-ms": { + "type": "integer" + }, + "sentinel": { + "type": "object", + "additionalProperties": true, + "nullable": true + } + } + }, + "scope": { + "type": "string", + "description": "The scope of policies evaluated in this check (e.g. \"organization\")." + }, + "status": { + "type": "string", + "enum": [ + "pending", + "queued", + "passed", + "soft_failed", + "hard_failed", + "overridden", + "errored", + "canceled", + "unreachable" + ] + }, + "status-timestamps": { + "type": "object", + "properties": { + "queued-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "passed-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "soft-failed-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "hard-failed-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "overridden-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "errored-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "actions": { + "type": "object", + "properties": { + "is-overridable": { + "type": "boolean" + } + } + }, + "permissions": { + "type": "object", + "properties": { + "can-override": { + "type": "boolean" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "run": { + "$ref": "#/components/schemas/runs-id" + } + } + }, + "links": { + "type": "object", + "properties": { + "output": { + "type": "string", + "nullable": true, + "description": "URL to download the policy check output log." + }, + "override": { + "type": "string", + "nullable": true, + "description": "URL to override a soft-failed policy check. Only present when the check is overridable." + } + } + } + } + }, + "policy-set-versions-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policy-set-versions" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "policies-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policies" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "policy-set": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "policy-sets" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "global": { + "type": "boolean" + }, + "workspace-count": { + "type": "integer" + }, + "project-count": { + "type": "integer" + }, + "versioned": { + "type": "boolean" + }, + "kind": { + "type": "string", + "enum": [ + "sentinel", + "opa", + "tfpolicy" + ] + }, + "agent-enabled": { + "type": "boolean" + }, + "policy-tool-version": { + "type": "string", + "nullable": true + }, + "overridable": { + "type": "boolean", + "nullable": true + }, + "policy-count": { + "type": "integer" + }, + "policies-path": { + "type": "string", + "nullable": true + }, + "vcs-repo": { + "type": "object", + "nullable": true, + "properties": { + "branch": { + "type": "string", + "nullable": true + }, + "identifier": { + "type": "string" + }, + "display-identifier": { + "type": "string", + "nullable": true + }, + "oauth-token-id": { + "type": "string", + "nullable": true + }, + "github-app-installation-id": { + "type": "string", + "nullable": true + }, + "ingress-submodules": { + "type": "boolean" + }, + "webhook-url": { + "type": "string", + "nullable": true + }, + "repository-http-url": { + "type": "string", + "nullable": true + }, + "service-provider": { + "type": "string", + "nullable": true + } + } + }, + "policy-update-patterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "evaluation-stages": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "enforcement-level": { + "type": "string", + "nullable": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "current-version": { + "$ref": "#/components/schemas/policy-set-versions-id" + }, + "newest-version": { + "$ref": "#/components/schemas/policy-set-versions-id" + }, + "policies": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policies-id" + } + } + } + }, + "workspaces": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspaces-id" + } + } + } + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/projects-id" + } + } + } + }, + "workspace-exclusions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspaces-id" + } + } + } + }, + "project-exclusions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/projects-id" + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "policy-set-version": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "policy-set-versions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "source": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "enum": [ + "pending", + "ingressing", + "ready", + "errored", + "canceled" + ] + }, + "status-timestamps": { + "type": "object", + "nullable": true, + "properties": { + "pending-at": { + "type": "string", + "format": "date-time" + }, + "ingressing-at": { + "type": "string", + "format": "date-time" + }, + "ready-at": { + "type": "string", + "format": "date-time" + }, + "errored-at": { + "type": "string", + "format": "date-time" + }, + "canceled-at": { + "type": "string", + "format": "date-time" + } + } + }, + "error": { + "type": "string", + "nullable": true + }, + "error-message": { + "type": "string", + "nullable": true + }, + "ingress-attributes": { + "type": "object", + "nullable": true, + "properties": { + "commit-sha": { + "type": "string", + "nullable": true + }, + "commit-url": { + "type": "string", + "nullable": true + }, + "identifier": { + "type": "string", + "nullable": true + } + } + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "policy-set": { + "$ref": "#/components/schemas/policy-sets-id" + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "upload": { + "type": "string", + "nullable": true + } + } + } + } + }, + "policy-evaluation": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "policy-evaluations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "pending", + "queued", + "running", + "passed", + "failed", + "overridden", + "errored", + "canceled", + "unreachable" + ] + }, + "policy-kind": { + "type": "string", + "enum": [ + "sentinel", + "opa" + ] + }, + "status-timestamps": { + "type": "object", + "properties": { + "pending-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "queued-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "running-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "passed-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "failed-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "overridden-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "errored-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "result-count": { + "type": "object", + "properties": { + "advisory-failed": { + "type": "integer" + }, + "mandatory-failed": { + "type": "integer" + }, + "passed": { + "type": "integer" + }, + "errored": { + "type": "integer" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "policy-attachable": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "task-stages" + ] + } + } + } + } + }, + "policy-set-outcomes": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policy-set-outcomes" + ] + } + } + } + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string" + } + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "policy-evaluations-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "policy-evaluations" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "policy-set-outcome": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "policy-set-outcomes" + ] + }, + "attributes": { + "type": "object", + "properties": { + "outcomes": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "enforcement_level": { + "type": "string", + "nullable": true + }, + "query": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string" + }, + "policy_name": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string" + }, + "output": { + "type": "array", + "nullable": true, + "items": {} + } + } + } + }, + "error": { + "type": "string", + "nullable": true + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + } + }, + "overridable": { + "type": "boolean" + }, + "policy-set-name": { + "type": "string" + }, + "policy-set-description": { + "type": "string", + "nullable": true + }, + "result-count": { + "type": "object", + "properties": { + "advisory-failed": { + "type": "integer" + }, + "mandatory-failed": { + "type": "integer" + }, + "passed": { + "type": "integer" + }, + "errored": { + "type": "integer" + } + } + }, + "policy-tool-version": { + "type": "string" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "policy-evaluation": { + "$ref": "#/components/schemas/policy-evaluations-id" + } + } + } + } + }, + "plan-export": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "plan-exports" + ] + }, + "attributes": { + "type": "object", + "properties": { + "data-type": { + "type": "string", + "enum": [ + "sentinel-mock-bundle-v0" + ] + }, + "status": { + "type": "string", + "enum": [ + "pending", + "queued", + "finished", + "expired", + "canceled", + "errored" + ] + }, + "status-timestamps": { + "type": "object", + "properties": { + "pending-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "queued-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "finished-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "expired-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "errored-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "error-message": { + "type": "string", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "plan": { + "$ref": "#/components/schemas/plans-id" + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "download": { + "type": "string", + "nullable": true + } + } + } + } + }, + "assessment-result": { + "type": "object", + "required": [ + "id", + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "example": "asmtres-8F5JFydVYAmtTjET" + }, + "type": { + "type": "string", + "enum": [ + "assessment-results" + ] + }, + "attributes": { + "type": "object", + "properties": { + "succeeded": { + "type": "boolean", + "description": "Whether the assessment completed successfully" + }, + "all-checks-succeeded": { + "type": "boolean", + "description": "Whether all health checks passed" + }, + "checks-errored": { + "type": "integer", + "description": "Number of health checks that errored", + "nullable": true + }, + "checks-failed": { + "type": "integer", + "description": "Number of health checks that failed", + "nullable": true + }, + "checks-passed": { + "type": "integer", + "description": "Number of health checks that passed", + "nullable": true + }, + "checks-unknown": { + "type": "integer", + "description": "Number of health checks with unknown status", + "nullable": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the assessment result was created" + }, + "drifted": { + "type": "boolean", + "description": "Whether drift was detected" + }, + "error-message": { + "type": "string", + "nullable": true, + "description": "Error message if the assessment failed" + }, + "resources-drifted": { + "type": "integer", + "nullable": true, + "description": "Number of resources that have drifted" + }, + "resources-undrifted": { + "type": "integer", + "nullable": true, + "description": "Number of resources that have not drifted" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspace": { + "type": "object", + "description": "The workspace this assessment result belongs to", + "properties": { + "data": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspaces" + ] + } + } + } + } + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "format": "uri", + "description": "API URL for this assessment result" + }, + "json-output": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the JSON formatted assessment output (available when assessment succeeded)" + }, + "json-schema": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the JSON schema of this assessment (available when assessment succeeded)" + }, + "sanitized-plan": { + "type": "string", + "format": "uri", + "nullable": true, + "description": "API URL for the sanitized plan (available when HYOK is enabled and assessment succeeded)", + "x-vis": [ + "public-beta" + ] + }, + "log-output": { + "type": "string", + "format": "uri", + "description": "API URL to read the logs for this assessment" + } + } + } + } + }, + "state-versions-id": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + } + } + }, + "apply": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "applies" + ] + }, + "attributes": { + "type": "object", + "properties": { + "execution-details": { + "type": "object", + "readOnly": true, + "nullable": true, + "properties": { + "mode": { + "type": "string", + "enum": [ + "agent", + "remote", + "local" + ] + }, + "agent-id": { + "type": "string" + }, + "agent-name": { + "type": "string" + }, + "agent-pool-id": { + "type": "string" + }, + "agent-pool-name": { + "type": "string" + } + } + }, + "status": { + "readOnly": true, + "type": "string", + "enum": [ + "created", + "pending", + "queued", + "agent_queued", + "running", + "errored", + "canceled", + "finished", + "unreachable" + ] + }, + "status-timestamps": { + "readOnly": true, + "type": "object", + "properties": { + "agent-queued-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "started-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "errored-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "force-canceled-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "finished-at": { + "type": "string", + "format": "date-time", + "nullable": true + } + } + }, + "log-read-url": { + "readOnly": true, + "type": "string" + }, + "resource-additions": { + "readOnly": true, + "type": "integer", + "nullable": true + }, + "resource-changes": { + "readOnly": true, + "type": "integer", + "nullable": true + }, + "resource-destructions": { + "readOnly": true, + "type": "integer", + "nullable": true + }, + "resource-imports": { + "readOnly": true, + "type": "integer", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "state-versions": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/state-versions-id" + } + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "cost-estimate": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "cost-estimates" + ] + }, + "attributes": { + "type": "object", + "properties": { + "error-message": { + "type": "string", + "nullable": true + }, + "status": { + "type": "string", + "enum": [ + "pending", + "queued", + "finished", + "canceled", + "errored", + "unreachable", + "skipped_due_to_targeting" + ] + }, + "status-timestamps": { + "type": "object", + "properties": { + "pending-at": { + "type": "string", + "format": "date-time" + }, + "queued-at": { + "type": "string", + "format": "date-time" + }, + "finished-at": { + "type": "string", + "format": "date-time" + }, + "canceled-at": { + "type": "string", + "format": "date-time" + }, + "errored-at": { + "type": "string", + "format": "date-time" + }, + "skipped-due-to-targeting-at": { + "type": "string", + "format": "date-time" + } + } + }, + "resources": { + "type": "object", + "nullable": true, + "description": "Low-level cost estimation details, only present when status is \"finished\". The keys or structure of this hash may change over time.", + "properties": { + "matched": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + }, + "unmatched": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "resources-count": { + "type": "integer", + "nullable": true, + "description": "Total number of resources. Only present when status is \"finished\"." + }, + "matched-resources-count": { + "type": "integer", + "nullable": true, + "description": "Number of matched resources. Only present when status is \"finished\"." + }, + "unmatched-resources-count": { + "type": "integer", + "nullable": true, + "description": "Number of unmatched resources. Only present when status is \"finished\"." + }, + "prior-monthly-cost": { + "type": "string", + "nullable": true, + "description": "Prior monthly cost as a decimal string. Only present when status is \"finished\"." + }, + "proposed-monthly-cost": { + "type": "string", + "nullable": true, + "description": "Proposed monthly cost as a decimal string. Only present when status is \"finished\"." + }, + "delta-monthly-cost": { + "type": "string", + "nullable": true, + "description": "Delta monthly cost as a decimal string. Only present when status is \"finished\"." + } + } + } + } + }, + "state-version": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "size": { + "type": "integer", + "nullable": true, + "readOnly": true + }, + "hosted-state-download-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "hosted-json-state-download-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "hosted-state-upload-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "hosted-json-state-upload-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "encrypted-state-download-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "sanitized-state-download-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "sanitized-state-upload-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "modules": { + "type": "object", + "nullable": true, + "readOnly": true, + "additionalProperties": true + }, + "providers": { + "type": "object", + "nullable": true, + "readOnly": true, + "additionalProperties": true + }, + "resources": { + "type": "array", + "nullable": true, + "readOnly": true, + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "count": { + "type": "integer" + }, + "module": { + "type": "string" + }, + "provider": { + "type": "string" + } + } + } + }, + "resources-processed": { + "type": "boolean", + "readOnly": true + }, + "serial": { + "type": "integer" + }, + "state-version": { + "type": "integer", + "nullable": true, + "readOnly": true + }, + "status": { + "type": "string", + "readOnly": true, + "enum": [ + "pending", + "finalized", + "discarded", + "backing_data_soft_deleted", + "backing_data_permanently_deleted" + ] + }, + "terraform-version": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "vcs-commit-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "vcs-commit-sha": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "intermediate": { + "type": "boolean", + "readOnly": true + }, + "billable-rum-count": { + "type": "integer", + "nullable": true, + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "run": { + "$ref": "#/components/schemas/runs-id" + }, + "rollback-state-version": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + } + } + } + } + }, + "next-state-version": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + } + } + } + } + }, + "previous-state-version": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-versions" + ] + } + } + } + } + }, + "created-by": { + "$ref": "#/components/schemas/users-id" + }, + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + }, + "hyok-encrypted-data-key": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "hyok-encrypted-data-keys" + ] + } + } + } + } + }, + "outputs": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "state-version-outputs" + ] + } + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "state-version-output": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "state-version-outputs" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "sensitive": { + "type": "boolean" + }, + "type": { + "type": "string", + "description": "The Terraform type of the output value (e.g. \"string\", \"number\", \"bool\", \"list\", \"map\", \"set\", \"object\", \"tuple\")." + }, + "value": { + "description": "The output value. Null when the output is sensitive and the caller does not have permission to reveal sensitive values.", + "nullable": true + }, + "detailed-type": { + "description": "A detailed representation of the output type. May be a string for simple types or an array for complex types such as tuples and objects." + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "authentication-token": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "authentication-tokens" + ] + }, + "attributes": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "expired-at": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "last-used-at": { + "type": "string", + "format": "date-time", + "readOnly": true, + "nullable": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "token": { + "type": "string", + "readOnly": true, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "team": { + "$ref": "#/components/schemas/links_related", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + } + }, + "created-by": { + "$ref": "#/components/schemas/links_related", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "github-app-oauth-token": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "github-app-oauth-tokens" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "github-username": { + "type": "string", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "user": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + } + } + } + } + }, + "teams-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "teams" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "team-project": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "team-projects" + ] + }, + "attributes": { + "type": "object", + "required": [ + "access" + ], + "properties": { + "access": { + "type": "string", + "enum": [ + "read", + "write", + "maintain", + "admin", + "custom" + ], + "description": "The access level granted to the team on the project." + }, + "project-access": { + "type": "object", + "description": "Fine-grained project access permissions. Only meaningful when access is \"custom\".", + "properties": { + "settings": { + "type": "string", + "enum": [ + "read", + "update", + "delete" + ], + "description": "Permission level for project settings." + }, + "teams": { + "type": "string", + "enum": [ + "none", + "read", + "manage" + ], + "description": "Permission level for managing project teams." + }, + "variable-sets": { + "type": "string", + "nullable": true, + "description": "Permission level for project variable sets." + } + } + }, + "workspace-access": { + "type": "object", + "description": "Fine-grained workspace access permissions. Only meaningful when access is \"custom\".", + "properties": { + "create": { + "type": "boolean", + "description": "Whether the team can create workspaces in the project." + }, + "move": { + "type": "boolean", + "description": "Whether the team can move workspaces into and out of the project." + }, + "locking": { + "type": "boolean", + "description": "Whether the team can manually lock or unlock the project's workspaces." + }, + "delete": { + "type": "boolean", + "description": "Whether the team can delete the project's workspaces." + }, + "runs": { + "type": "string", + "enum": [ + "read", + "plan", + "apply" + ], + "description": "Permission level for workspace runs." + }, + "variables": { + "type": "string", + "enum": [ + "none", + "read", + "write" + ], + "description": "Permission level for workspace variables." + }, + "state-versions": { + "type": "string", + "enum": [ + "none", + "read-outputs", + "read", + "write" + ], + "description": "Permission level for workspace state versions." + }, + "sentinel-mocks": { + "type": "string", + "enum": [ + "none", + "read" + ], + "description": "Permission level for workspace Sentinel mocks." + }, + "run-tasks": { + "type": "boolean", + "description": "Whether the team can manage run tasks within the project's workspaces." + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "team": { + "$ref": "#/components/schemas/teams-id" + }, + "project": { + "$ref": "#/components/schemas/projects-id" + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + } + } + } + } + }, + "team-workspace": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "team-workspaces" + ] + }, + "attributes": { + "type": "object", + "required": [ + "access" + ], + "properties": { + "access": { + "type": "string", + "enum": [ + "read", + "plan", + "write", + "admin", + "custom" + ], + "description": "The type of access the team has on the workspace. Valid values are read, plan, write, admin, or custom." + }, + "runs": { + "type": "string", + "enum": [ + "read", + "plan", + "apply" + ], + "description": "The permission for the workspace's runs. Can only be used when access is custom." + }, + "variables": { + "type": "string", + "enum": [ + "none", + "read", + "write" + ], + "description": "The permission for the workspace's variables. Can only be used when access is custom." + }, + "state-versions": { + "type": "string", + "enum": [ + "none", + "read-outputs", + "read", + "write" + ], + "description": "The permission for the workspace's state versions. Can only be used when access is custom." + }, + "sentinel-mocks": { + "type": "string", + "enum": [ + "none", + "read" + ], + "description": "The permission for the workspace's Sentinel mocks. Can only be used when access is custom." + }, + "workspace-locking": { + "type": "boolean", + "description": "Whether the team can manually lock or unlock the workspace. Can only be used when access is custom." + }, + "run-tasks": { + "type": "boolean", + "description": "Whether the team can manage run tasks within the workspace. Can only be used when access is custom." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "team": { + "$ref": "#/components/schemas/teams-id" + }, + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "integration": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The external ID of the integration.", + "example": "int-xxxxxxxxxxxxxxxx" + }, + "type": { + "type": "string", + "enum": [ + "integrations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the integration.", + "example": "Cloudability" + }, + "provider": { + "type": "string", + "description": "The provider identifier for the integration.", + "example": "cloudability" + }, + "description": { + "type": "string", + "description": "A description of what the integration does.", + "example": "Cloud cost management" + }, + "homepage": { + "type": "string", + "format": "uri", + "description": "The homepage URL for the integration.", + "example": "https://www.apptio.com/products/cloudability/" + }, + "stages": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The run stages where this integration can be used.", + "example": [ + "post_plan" + ] + }, + "params": { + "type": "object", + "description": "Configuration parameters required by the integration.", + "additionalProperties": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "description": "The type of the parameter." + }, + "sensitive": { + "type": "boolean", + "description": "Whether the parameter contains sensitive data." + }, + "required": { + "type": "boolean", + "description": "Whether the parameter is required." + }, + "description": { + "type": "string", + "description": "Description of the parameter." + } + } + } + } + }, + "required": [ + "name", + "provider", + "description", + "homepage", + "stages", + "params" + ] + } + }, + "required": [ + "id", + "type", + "attributes" + ] + }, + "ingress-attributes": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "ingress-attributes" + ] + }, + "attributes": { + "type": "object", + "properties": { + "branch": { + "type": "string" + }, + "clone-url": { + "type": "string" + }, + "commit-message": { + "type": "string" + }, + "commit-sha": { + "type": "string" + }, + "commit-url": { + "type": "string" + }, + "compare-url": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "is-pull-request": { + "type": "boolean" + }, + "on-default-branch": { + "type": "boolean" + }, + "pull-request-number": { + "type": "integer" + }, + "pull-request-url": { + "type": "string" + }, + "pull-request-title": { + "type": "string" + }, + "pull-request-body": { + "type": "string" + }, + "tag": { + "type": "string", + "nullable": true + }, + "sender-username": { + "type": "string" + }, + "sender-avatar-url": { + "type": "string" + }, + "sender-html-url": { + "type": "string" + } + } + }, + "relationships": { + "type": "object", + "properties": { + "created-by": { + "$ref": "#/components/schemas/users-id" + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "oauth-clients-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "oauth-clients" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "oauth-tokens-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "oauth-tokens" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "vcs-event": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "vcs-events" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "level": { + "type": "string" + }, + "message": { + "type": "string", + "nullable": true + }, + "organization-id": { + "type": "integer" + }, + "suggested-action": { + "type": "string", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "oauth-client": { + "$ref": "#/components/schemas/oauth-clients-id" + }, + "oauth-token": { + "$ref": "#/components/schemas/oauth-tokens-id" + } + } + } + } + }, + "ssh-key": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the SSH key.", + "example": "sshkey-xxxxxxxxxxxxxxxx" + }, + "type": { + "type": "string", + "enum": [ + "ssh-keys" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the SSH key.", + "example": "My SSH Key" + } + }, + "required": [ + "name" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "format": "uri", + "description": "The path to the SSH key.", + "example": "/api/v2/ssh-keys/sshkey-xxxxxxxxxxxxxxxx" + } + }, + "required": [ + "self" + ] + } + }, + "required": [ + "id", + "type", + "attributes", + "links" + ] + }, + "change-request": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "workspace-change-requests" + ] + }, + "attributes": { + "type": "object", + "properties": { + "subject": { + "type": "string" + }, + "message": { + "type": "string", + "nullable": true + }, + "archived-at": { + "type": "string", + "format": "date-time", + "nullable": true, + "readOnly": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + }, + "created-by": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "archived-by-user": { + "type": "object", + "properties": { + "data": { + "type": "object", + "nullable": true, + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "users" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + } + } + } + } + }, + "oauth-client": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "oauth-clients" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "callback-url": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "connect-path": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "service-provider": { + "type": "string" + }, + "service-provider-display-name": { + "type": "string", + "readOnly": true + }, + "http-url": { + "type": "string", + "nullable": true + }, + "api-url": { + "type": "string", + "nullable": true + }, + "key": { + "type": "string", + "nullable": true + }, + "ado-entra-tenant-id": { + "type": "string", + "nullable": true + }, + "secret": { + "type": "string", + "nullable": true + }, + "rsa-public-key": { + "type": "string", + "nullable": true + }, + "uuid": { + "type": "string", + "readOnly": true + }, + "organization-scoped": { + "type": "boolean" + }, + "affected-workspaces": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "affected-workspaces-count": { + "type": "integer", + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "agent-pool": { + "$ref": "#/components/schemas/agent-pools-id" + }, + "projects": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "projects" + ] + } + } + } + } + } + }, + "oauth-tokens": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object", + "required": [ + "id", + "type" + ], + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "oauth-tokens" + ] + } + } + } + }, + "links": { + "type": "object", + "properties": { + "related": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "oauth-token": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "oauth-tokens" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "service-provider-user": { + "type": "string", + "nullable": true, + "readOnly": true + }, + "has-ssh-key": { + "type": "boolean", + "readOnly": true + }, + "ssh-key": { + "type": "string", + "nullable": true, + "writeOnly": true, + "description": "The SSH private key. Write-only; use has-ssh-key to check if a key has been set." + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + }, + "relationships": { + "type": "object", + "properties": { + "oauth-client": { + "$ref": "#/components/schemas/oauth-clients-id" + }, + "vcs-organizations": { + "$ref": "#/components/schemas/links_related" + } + } + } + } + }, + "authorized-repo": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "authorized-repos" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "readOnly": true + }, + "display-identifier": { + "type": "string", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "oauth-token": { + "$ref": "#/components/schemas/oauth-tokens-id" + } + } + } + } + }, + "vcs-organization": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "vcs-organization" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "readOnly": true + } + } + } + } + }, + "github-app-installation": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "github-app-installations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "installation-id": { + "type": "integer", + "nullable": true + }, + "icon-url": { + "type": "string", + "nullable": true + }, + "installation-type": { + "type": "string", + "nullable": true + }, + "installation-url": { + "type": "string", + "nullable": true + } + } + } + } + }, + "github-app-repo": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "github-app-repos" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true + }, + "identifier": { + "type": "string", + "nullable": true + }, + "installation-id": { + "type": "string", + "nullable": true + }, + "private": { + "type": "boolean", + "nullable": true + } + } + } + } + }, + "workspace-tasks-id": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "workspace-tasks" + ] + } + } + }, + "task": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "tasks" + ] + }, + "attributes": { + "type": "object", + "properties": { + "category": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string", + "nullable": true + }, + "url": { + "type": "string" + }, + "hmac-key": { + "type": "string", + "nullable": true + }, + "enabled": { + "type": "boolean" + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "global-configuration": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "stages": { + "type": "array", + "items": { + "type": "string" + } + }, + "enforcement-level": { + "type": "string", + "nullable": true + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "$ref": "#/components/schemas/organizations-id" + }, + "workspace-tasks": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/workspace-tasks-id" + } + } + } + }, + "agent-pool": { + "$ref": "#/components/schemas/agent-pools-id" + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "tasks-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "tasks" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "workspace-task": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "workspace-tasks" + ] + }, + "attributes": { + "type": "object", + "properties": { + "enforcement-level": { + "type": "string", + "enum": [ + "advisory", + "mandatory" + ] + }, + "stage": { + "type": "string", + "description": "Deprecated. Use `stages` instead. The stage in the run lifecycle when the run task should begin.\n" + }, + "stages": { + "type": "array", + "items": { + "type": "string" + } + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "task": { + "$ref": "#/components/schemas/tasks-id" + }, + "workspace": { + "$ref": "#/components/schemas/workspaces-id" + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "task-results-id": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "task-results" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "task-stage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "task-stages" + ] + }, + "attributes": { + "type": "object", + "properties": { + "status": { + "type": "string", + "readOnly": true, + "enum": [ + "pending", + "running", + "passed", + "failed", + "awaiting_override", + "errored", + "canceled", + "unreachable" + ] + }, + "stage": { + "type": "string", + "readOnly": true, + "description": "The run stage during which this task stage executes (e.g., post_plan, pre_plan, pre_apply, post_apply)." + }, + "status-timestamps": { + "type": "object", + "nullable": true, + "readOnly": true, + "additionalProperties": true, + "description": "A map of status names to timestamps indicating when the task stage entered each status. Keys are formatted as \"{status}-at\"." + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "permissions": { + "type": "object", + "readOnly": true, + "properties": { + "can-override-policy": { + "type": "boolean" + }, + "can-override-tasks": { + "type": "boolean" + }, + "can-override": { + "type": "boolean" + } + } + }, + "actions": { + "type": "object", + "readOnly": true, + "properties": { + "is-overridable": { + "type": "boolean" + } + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "run": { + "$ref": "#/components/schemas/runs-id" + }, + "cost-estimate": { + "type": "object", + "properties": { + "data": { + "nullable": true, + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "enum": [ + "cost-estimates" + ] + } + } + }, + "links": { + "$ref": "#/components/schemas/related" + } + } + }, + "task-results": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/task-results-id" + } + } + } + }, + "policy-evaluations": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/policy-evaluations-id" + } + } + } + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "task-result": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "task-results" + ] + }, + "attributes": { + "type": "object", + "properties": { + "message": { + "type": "string", + "nullable": true, + "description": "A message describing the result of the run task execution." + }, + "status": { + "type": "string", + "readOnly": true, + "enum": [ + "pending", + "running", + "passed", + "failed", + "errored", + "canceled", + "unreachable" + ] + }, + "status-timestamps": { + "type": "object", + "nullable": true, + "readOnly": true, + "additionalProperties": true, + "description": "A map of status names to timestamps indicating when the task result entered each status. Keys are formatted as \"{status}-at\"." + }, + "url": { + "type": "string", + "nullable": true, + "description": "A URL the run task integration provided with details about the task execution." + }, + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "updated-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "task-id": { + "type": "string", + "readOnly": true, + "description": "The external ID of the run task." + }, + "task-name": { + "type": "string", + "readOnly": true, + "description": "The name of the run task." + }, + "task-url": { + "type": "string", + "nullable": true, + "readOnly": true, + "description": "The URL of the run task definition." + }, + "task-result-outcomes-count": { + "type": "integer", + "readOnly": true, + "description": "The number of task result outcomes associated with this task result." + }, + "stage": { + "type": "string", + "readOnly": true, + "description": "The run stage during which this task result was created." + }, + "is-speculative": { + "type": "boolean", + "readOnly": true, + "description": "Whether the associated run is speculative (plan-only)." + }, + "workspace-task-id": { + "type": "string", + "nullable": true, + "readOnly": true, + "description": "The external ID of the workspace task configuration." + }, + "workspace-task-enforcement-level": { + "type": "string", + "nullable": true, + "readOnly": true, + "description": "The enforcement level of the workspace task (e.g., advisory, mandatory)." + }, + "agent-pool-id": { + "type": "string", + "nullable": true, + "readOnly": true, + "description": "The external ID of the agent pool, when private run tasks are enabled." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "task-stage": { + "$ref": "#/components/schemas/task-stages-id" + }, + "task-result-outcomes": { + "$ref": "#/components/schemas/links_related" + } + } + }, + "links": { + "$ref": "#/components/schemas/self" + } + } + }, + "task-result-outcome": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "enum": [ + "task-result-outcomes" + ] + }, + "attributes": { + "type": "object", + "properties": { + "created-at": { + "type": "string", + "format": "date-time", + "readOnly": true + }, + "outcome-id": { + "type": "string", + "description": "A unique identifier for this outcome within the run task result." + }, + "description": { + "type": "string", + "description": "A human-readable description of this outcome." + }, + "tags": { + "type": "array", + "nullable": true, + "items": { + "type": "object", + "properties": { + "label": { + "type": "string", + "description": "The tag category name." + }, + "value": { + "type": "array", + "items": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "level": { + "type": "string" + } + } + } + } + } + }, + "description": "An array of tag category objects. Each object has a label (category name) and a value array of tag entries with label and level fields." + }, + "url": { + "type": "string", + "nullable": true, + "description": "A URL with additional details about this outcome." + } + } + }, + "relationships": { + "type": "object", + "properties": { + "task-result": { + "$ref": "#/components/schemas/task-results-id" + } + } + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string" + }, + "body": { + "type": "string", + "nullable": true, + "description": "URL to download the outcome body. Only present when the run task integration uploaded a body for this outcome." + } + } + } + } + } + }, + "parameters": { + "page_number": { + "name": "page[number]", + "in": "query", + "description": "The page number to retrieve.", + "schema": { + "type": "integer", + "example": 1 + } + }, + "page_size": { + "name": "page[size]", + "in": "query", + "description": "The number of items to retrieve per page. Defaults to 20.", + "schema": { + "type": "integer", + "example": 20 + } + } + } + } +} \ No newline at end of file diff --git a/internal/commands/api/schema.go b/internal/commands/api/schema.go index 9230a6b..f5abf4e 100644 --- a/internal/commands/api/schema.go +++ b/internal/commands/api/schema.go @@ -19,14 +19,17 @@ type schemaOperation struct { Summary string } +type schemaOperationsLoader func(ctx *cmd.Context) ([]schemaOperation, error) +type schemaDocumentLoader func(ctx *cmd.Context) (map[string]any, error) + type schemaSearcher interface { Search(ctx context.Context, query string, operations []schemaOperation, limit int) ([]schemaSearchResult, error) } var ( - loadSchemaOperationsForSearch = cachedSchemaOperations - loadSchemaDocumentForGet = cachedSchemaDocument - schemaOperationSearcher schemaSearcher = hybridSchemaSearcher{} + loadSchemaOperationsForSearch schemaOperationsLoader = cachedSchemaOperations + loadSchemaDocumentForGet schemaDocumentLoader = cachedSchemaDocument + schemaOperationSearcher schemaSearcher = hybridSchemaSearcher{} ) func NewCmdAPISchema(ctx *cmd.Context) *cmd.Command { @@ -68,7 +71,7 @@ func newCmdAPISchemaSearch(ctx *cmd.Context) *cmd.Command { }}, RunF: func(_ *cmd.Command, args []string) error { query := joinSchemaQuery(args) - operations, err := loadSchemaOperationsForSearch() + operations, err := loadSchemaOperationsForSearch(ctx) if err != nil { return err } @@ -121,7 +124,7 @@ func newCmdAPISchemaGet(ctx *cmd.Context) *cmd.Command { Command: "$ tfcloud api schema get getWorkspace", }}, RunF: func(_ *cmd.Command, args []string) error { - document, err := loadSchemaDocumentForGet() + document, err := loadSchemaDocumentForGet(ctx) if err != nil { return err } diff --git a/internal/commands/api/schema_eval_test.go b/internal/commands/api/schema_eval_test.go index 1281c94..56c11d6 100644 --- a/internal/commands/api/schema_eval_test.go +++ b/internal/commands/api/schema_eval_test.go @@ -6,6 +6,8 @@ import ( "fmt" "strings" "testing" + + "github.com/hashicorp/tfcloud/internal/pkg/iostreams" ) type schemaSearchFixture struct { @@ -120,7 +122,7 @@ func TestSchemaSearchSummary(t *testing.T) { } func TestSpecBackedSchemaSearch(t *testing.T) { - operations, err := loadSchemaOperationsForSearch() + operations, err := loadSchemaOperationsForSearch(testCommandContext(iostreams.Test())) if err != nil { t.Fatal(err) } diff --git a/internal/commands/api/schema_spec.go b/internal/commands/api/schema_spec.go index be10990..0c2fa43 100644 --- a/internal/commands/api/schema_spec.go +++ b/internal/commands/api/schema_spec.go @@ -3,12 +3,15 @@ package api import ( "encoding/json" "fmt" - "os" - "path/filepath" - "runtime" + "net/http" "sort" "strings" "sync" + + _ "embed" + + "github.com/hashicorp/tfcloud/internal/pkg/client" + "github.com/hashicorp/tfcloud/internal/pkg/cmd" ) type openAPISpec struct { @@ -22,6 +25,8 @@ type openAPIOperation struct { Tags []string `json:"tags"` } +var embeddedOpenAPISpec []byte + var ( schemaOperationsOnce sync.Once schemaOperationsCache []schemaOperation @@ -31,53 +36,79 @@ var ( schemaDocumentErr error ) -func cachedSchemaOperations() ([]schemaOperation, error) { +func cachedSchemaOperations(ctx *cmd.Context) ([]schemaOperation, error) { schemaOperationsOnce.Do(func() { - specPath, err := defaultOpenAPISpecPath() + data, source, err := loadSchemaSpecBytes(ctx) if err != nil { schemaOperationsErr = err return } - schemaOperationsCache, schemaOperationsErr = loadSchemaOperationsFromSpec(specPath) + schemaOperationsCache, schemaOperationsErr = loadSchemaOperationsFromBytes(data, source) }) return schemaOperationsCache, schemaOperationsErr } -func cachedSchemaDocument() (map[string]any, error) { +func cachedSchemaDocument(ctx *cmd.Context) (map[string]any, error) { schemaDocumentOnce.Do(func() { - specPath, err := defaultOpenAPISpecPath() + data, source, err := loadSchemaSpecBytes(ctx) if err != nil { schemaDocumentErr = err return } - schemaDocumentCache, schemaDocumentErr = loadSchemaDocumentFromSpec(specPath) + schemaDocumentCache, schemaDocumentErr = loadSchemaDocumentFromBytes(data, source) }) return schemaDocumentCache, schemaDocumentErr } -func loadSchemaDocumentFromSpec(specPath string) (map[string]any, error) { - data, err := os.ReadFile(specPath) +func loadSchemaSpecBytes(ctx *cmd.Context) ([]byte, string, error) { + if hosted, err := fetchHostedOpenAPISpec(ctx); err == nil { + return hosted, "from host", nil + } + if len(embeddedOpenAPISpec) == 0 { + return nil, "", fmt.Errorf("embedded OpenAPI spec is empty") + } + return embeddedOpenAPISpec, "from embedded fallback", nil +} + +func fetchHostedOpenAPISpec(ctx *cmd.Context) ([]byte, error) { + if ctx == nil || ctx.APIClient == nil || ctx.APIClient.BaseURL == nil { + return nil, fmt.Errorf("hosted OpenAPI spec unavailable without API client") + } + + requestURL, err := client.ResolveURL(ctx.APIClient.BaseURL, "/api/v2/openapi.json") + if err != nil { + return nil, err + } + + resp, err := ctx.APIClient.RawRequest(schemaSearchContext(ctx), &client.Request{ + Method: http.MethodGet, + URL: requestURL, + }) if err != nil { - return nil, fmt.Errorf("read OpenAPI spec %q: %w", specPath, err) + return nil, err } + if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusForbidden { + return nil, fmt.Errorf("hosted OpenAPI spec unavailable: %s", resp.Status) + } + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return nil, fmt.Errorf("fetch hosted OpenAPI spec: %s", resp.Status) + } + return resp.Body, nil +} +func loadSchemaDocumentFromBytes(data []byte, source string) (map[string]any, error) { var document map[string]any if err := json.Unmarshal(data, &document); err != nil { - return nil, fmt.Errorf("parse OpenAPI spec %q: %w", specPath, err) + return nil, fmt.Errorf("parse OpenAPI spec %s: %w", source, err) } return document, nil } -func loadSchemaOperationsFromSpec(specPath string) ([]schemaOperation, error) { - data, err := os.ReadFile(specPath) - if err != nil { - return nil, fmt.Errorf("read OpenAPI spec %q: %w", specPath, err) - } - +func loadSchemaOperationsFromBytes(data []byte, source string) ([]schemaOperation, error) { var spec openAPISpec if err := json.Unmarshal(data, &spec); err != nil { - return nil, fmt.Errorf("parse OpenAPI spec %q: %w", specPath, err) + return nil, fmt.Errorf("parse OpenAPI spec %s: %w", source, err) } operations := make([]schemaOperation, 0, len(spec.Paths)) @@ -126,44 +157,12 @@ func loadSchemaOperationsFromSpec(specPath string) ([]schemaOperation, error) { }) if len(operations) == 0 { - return nil, fmt.Errorf("no API operations found in OpenAPI spec %q", specPath) + return nil, fmt.Errorf("no API operations found in OpenAPI spec %s", source) } return operations, nil } -func defaultOpenAPISpecPath() (string, error) { - _, filename, _, ok := runtime.Caller(0) - if !ok { - return "", fmt.Errorf("resolve schema command source path") - } - - repoRoot := filepath.Clean(filepath.Join(filepath.Dir(filename), "..", "..", "..")) - goModPath := filepath.Join(repoRoot, "go.mod") - candidates := []string{filepath.Join(repoRoot, "openapi", "spec.json")} - - if replaceTarget, err := goModReplaceTarget(goModPath, "github.com/hashicorp/go-tfe"); err == nil && replaceTarget != "" { - if !filepath.IsAbs(replaceTarget) { - replaceTarget = filepath.Join(repoRoot, replaceTarget) - } - candidates = append(candidates, filepath.Join(replaceTarget, "openapi", "spec.json")) - } - - candidates = append(candidates, - filepath.Join(repoRoot, "..", "go-tfe", "openapi", "spec.json"), - filepath.Join(filepath.Dir(repoRoot), "go-tfe", "openapi", "spec.json"), - "/Users/shweta.murali/go-tfe/openapi/spec.json", - ) - - for _, candidate := range candidates { - if _, err := os.Stat(candidate); err == nil { - return candidate, nil - } - } - - return "", fmt.Errorf("could not locate an OpenAPI spec; checked %s", strings.Join(candidates, ", ")) -} - func schemaOperationDocument(spec map[string]any, operationID string) (map[string]any, error) { pathValue, ok := spec["paths"].(map[string]any) if !ok { @@ -338,31 +337,6 @@ func cloneValue(value any) any { } } -func goModReplaceTarget(goModPath, modulePath string) (string, error) { - data, err := os.ReadFile(goModPath) - if err != nil { - return "", err - } - - for _, line := range strings.Split(string(data), "\n") { - line = strings.TrimSpace(line) - if !strings.HasPrefix(line, "replace ") || !strings.Contains(line, modulePath) || !strings.Contains(line, "=>") { - continue - } - parts := strings.Fields(line) - if len(parts) < 4 { - continue - } - for i := 0; i < len(parts)-1; i++ { - if parts[i] == "=>" { - return parts[i+1], nil - } - } - } - - return "", fmt.Errorf("replace target for %s not found", modulePath) -} - func isHTTPMethod(method string) bool { switch strings.ToLower(method) { case "get", "post", "put", "patch", "delete": diff --git a/internal/commands/api/schema_test.go b/internal/commands/api/schema_test.go index a5bccad..159600c 100644 --- a/internal/commands/api/schema_test.go +++ b/internal/commands/api/schema_test.go @@ -47,7 +47,7 @@ func TestCmdAPISchemaSearchRun(t *testing.T) { io := iostreams.Test() originalLoader := loadSchemaOperationsForSearch originalSearcher := schemaOperationSearcher - loadSchemaOperationsForSearch = func() ([]schemaOperation, error) { + loadSchemaOperationsForSearch = func(*cmd.Context) ([]schemaOperation, error) { return testSchemaOperations, nil } schemaOperationSearcher = hybridSchemaSearcher{} @@ -162,7 +162,7 @@ func TestCmdAPISchemaGetRun(t *testing.T) { io := iostreams.Test() originalLoader := loadSchemaDocumentForGet - loadSchemaDocumentForGet = func() (map[string]any, error) { + loadSchemaDocumentForGet = func(*cmd.Context) (map[string]any, error) { return map[string]any{ "openapi": "3.0.0", "paths": map[string]any{ @@ -189,6 +189,22 @@ func TestCmdAPISchemaGetRun(t *testing.T) { r.Empty(io.Error.String()) } +func TestLoadSchemaSpecBytesFallsBackToEmbedded(t *testing.T) { + t.Parallel() + + ctx := testCommandContext(iostreams.Test()) + data, source, err := loadSchemaSpecBytes(ctx) + if err != nil { + t.Fatal(err) + } + if len(data) == 0 { + t.Fatal("expected embedded spec bytes") + } + if source != "from embedded fallback" { + t.Fatalf("expected embedded fallback source, got %q", source) + } +} + func testCommandContext(io *iostreams.Testing) *cmd.Context { return &cmd.Context{ IO: io, From 55942d545016c54f5120c6126c29b6c1bf14d825 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:52:14 -0400 Subject: [PATCH 10/14] Update internal/commands/api/schema_search_helpers.go Co-authored-by: Brandon Croft --- internal/commands/api/schema_search_helpers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/api/schema_search_helpers.go b/internal/commands/api/schema_search_helpers.go index 6f99cc0..a79fbdc 100644 --- a/internal/commands/api/schema_search_helpers.go +++ b/internal/commands/api/schema_search_helpers.go @@ -169,7 +169,7 @@ func normalizeToken(token string) string { return "create" case "show", "fetch", "read", "find": return "get" - case "all", "browse": + case "all", "browse", "collection", "index": return "list" case "remove", "destroy": return "delete" From 2ed3237ccd7f87edd20f630b530efd323904cce4 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:46:21 -0400 Subject: [PATCH 11/14] Create pull_request_template.md --- .github/pull_request_template.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..fb2546b --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## PCI review checklist + + + +- [ ] I have documented a clear reason for, and description of, the change I am making. + +- [ ] If applicable, I've documented a plan to revert these changes if they require more than reverting the pull request. + +- [ ] If applicable, I've documented the impact of any changes to security controls. + + Examples of changes to security controls include using new access control methods, adding or removing logging pipelines, etc. + +If you have any questions, please contact your direct supervisor, GRC (#team-grc), or the PCI working group (#proj-pci-reboot). You can also find more information at [PCI Compliance](https://hashicorp.atlassian.net/wiki/spaces/SEC/pages/2784559202/PCI+Compliance). From b2fffbb240fcb04a2acaccec19a10effa8cd4041 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:52:07 -0400 Subject: [PATCH 12/14] Update schema_spec.go --- internal/commands/api/schema_spec.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/commands/api/schema_spec.go b/internal/commands/api/schema_spec.go index 0c2fa43..ed9305d 100644 --- a/internal/commands/api/schema_spec.go +++ b/internal/commands/api/schema_spec.go @@ -25,6 +25,7 @@ type openAPIOperation struct { Tags []string `json:"tags"` } +//go:embed openapi/spec.json var embeddedOpenAPISpec []byte var ( From ec2ceb3f141c8e2615be0b57b273c846eb5b6117 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Mon, 13 Apr 2026 18:55:51 -0400 Subject: [PATCH 13/14] Update schema.go --- internal/commands/api/schema.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/commands/api/schema.go b/internal/commands/api/schema.go index f5abf4e..9d5c5fc 100644 --- a/internal/commands/api/schema.go +++ b/internal/commands/api/schema.go @@ -32,6 +32,7 @@ var ( schemaOperationSearcher schemaSearcher = hybridSchemaSearcher{} ) +// NewCmdAPISchema creates the api schema command group. func NewCmdAPISchema(ctx *cmd.Context) *cmd.Command { c := &cmd.Command{ Name: "schema", From c9ab8245267afb396f0cf5273ddae0b2fd5be0d4 Mon Sep 17 00:00:00 2001 From: Shweta <35878561+shwetamurali@users.noreply.github.com> Date: Wed, 15 Apr 2026 09:50:06 -0400 Subject: [PATCH 14/14] comment out openapi fetch logic --- internal/commands/api/schema_spec.go | 68 ++++++++++++++++------------ 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/internal/commands/api/schema_spec.go b/internal/commands/api/schema_spec.go index ed9305d..ad3e9e8 100644 --- a/internal/commands/api/schema_spec.go +++ b/internal/commands/api/schema_spec.go @@ -3,14 +3,12 @@ package api import ( "encoding/json" "fmt" - "net/http" "sort" "strings" "sync" _ "embed" - "github.com/hashicorp/tfcloud/internal/pkg/client" "github.com/hashicorp/tfcloud/internal/pkg/cmd" ) @@ -62,40 +60,50 @@ func cachedSchemaDocument(ctx *cmd.Context) (map[string]any, error) { } func loadSchemaSpecBytes(ctx *cmd.Context) ([]byte, string, error) { - if hosted, err := fetchHostedOpenAPISpec(ctx); err == nil { - return hosted, "from host", nil - } + // Always use the embedded fallback until the hosted OpenAPI endpoint is + // confirmed and deployed consistently on the platform. + _ = ctx + // + // When the platform endpoint is known and deployed consistently, restore the + // hosted-first path here: + // + // if hosted, err := fetchHostedOpenAPISpec(ctx); err == nil { + // return hosted, "from host", nil + // } if len(embeddedOpenAPISpec) == 0 { return nil, "", fmt.Errorf("embedded OpenAPI spec is empty") } return embeddedOpenAPISpec, "from embedded fallback", nil } -func fetchHostedOpenAPISpec(ctx *cmd.Context) ([]byte, error) { - if ctx == nil || ctx.APIClient == nil || ctx.APIClient.BaseURL == nil { - return nil, fmt.Errorf("hosted OpenAPI spec unavailable without API client") - } - - requestURL, err := client.ResolveURL(ctx.APIClient.BaseURL, "/api/v2/openapi.json") - if err != nil { - return nil, err - } - - resp, err := ctx.APIClient.RawRequest(schemaSearchContext(ctx), &client.Request{ - Method: http.MethodGet, - URL: requestURL, - }) - if err != nil { - return nil, err - } - if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusForbidden { - return nil, fmt.Errorf("hosted OpenAPI spec unavailable: %s", resp.Status) - } - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return nil, fmt.Errorf("fetch hosted OpenAPI spec: %s", resp.Status) - } - return resp.Body, nil -} +// Future hosted fetch path, intentionally disabled until the real endpoint is +// confirmed and deployed consistently on the platform. +// +// func fetchHostedOpenAPISpec(ctx *cmd.Context) ([]byte, error) { +// if ctx == nil || ctx.APIClient == nil || ctx.APIClient.BaseURL == nil { +// return nil, fmt.Errorf("hosted OpenAPI spec unavailable without API client") +// } +// +// requestURL, err := client.ResolveURL(ctx.APIClient.BaseURL, "/api/v2/openapi.json") +// if err != nil { +// return nil, err +// } +// +// resp, err := ctx.APIClient.RawRequest(schemaSearchContext(ctx), &client.Request{ +// Method: http.MethodGet, +// URL: requestURL, +// }) +// if err != nil { +// return nil, err +// } +// if resp.StatusCode == http.StatusNotFound || resp.StatusCode == http.StatusForbidden { +// return nil, fmt.Errorf("hosted OpenAPI spec unavailable: %s", resp.Status) +// } +// if resp.StatusCode < 200 || resp.StatusCode >= 300 { +// return nil, fmt.Errorf("fetch hosted OpenAPI spec: %s", resp.Status) +// } +// return resp.Body, nil +// } func loadSchemaDocumentFromBytes(data []byte, source string) (map[string]any, error) { var document map[string]any