sg-token-broker 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. sg_token_broker-0.1.0/.gitignore +46 -0
  2. sg_token_broker-0.1.0/LICENSE +21 -0
  3. sg_token_broker-0.1.0/PKG-INFO +208 -0
  4. sg_token_broker-0.1.0/README.md +176 -0
  5. sg_token_broker-0.1.0/pyproject.toml +171 -0
  6. sg_token_broker-0.1.0/src/sg_token_broker/__init__.py +33 -0
  7. sg_token_broker-0.1.0/src/sg_token_broker/__main__.py +8 -0
  8. sg_token_broker-0.1.0/src/sg_token_broker/_audit.py +33 -0
  9. sg_token_broker-0.1.0/src/sg_token_broker/_cache.py +189 -0
  10. sg_token_broker-0.1.0/src/sg_token_broker/_cli.py +711 -0
  11. sg_token_broker-0.1.0/src/sg_token_broker/_client.py +254 -0
  12. sg_token_broker-0.1.0/src/sg_token_broker/_config.py +299 -0
  13. sg_token_broker-0.1.0/src/sg_token_broker/_credstore.py +177 -0
  14. sg_token_broker-0.1.0/src/sg_token_broker/_downstream.py +143 -0
  15. sg_token_broker-0.1.0/src/sg_token_broker/_gclaims.py +174 -0
  16. sg_token_broker-0.1.0/src/sg_token_broker/_googleverify.py +61 -0
  17. sg_token_broker-0.1.0/src/sg_token_broker/_http.py +329 -0
  18. sg_token_broker-0.1.0/src/sg_token_broker/_httpbase.py +211 -0
  19. sg_token_broker-0.1.0/src/sg_token_broker/_oidcverify.py +258 -0
  20. sg_token_broker-0.1.0/src/sg_token_broker/_secrets.py +148 -0
  21. sg_token_broker-0.1.0/src/sg_token_broker/_service.py +363 -0
  22. sg_token_broker-0.1.0/src/sg_token_broker/_sg.py +285 -0
  23. sg_token_broker-0.1.0/src/sg_token_broker/_urlpolicy.py +54 -0
  24. sg_token_broker-0.1.0/src/sg_token_broker/_userauth.py +687 -0
  25. sg_token_broker-0.1.0/src/sg_token_broker/_userclient.py +270 -0
  26. sg_token_broker-0.1.0/src/sg_token_broker/_userconfig.py +219 -0
  27. sg_token_broker-0.1.0/src/sg_token_broker/_userhttp.py +208 -0
  28. sg_token_broker-0.1.0/src/sg_token_broker/_users.py +147 -0
  29. sg_token_broker-0.1.0/src/sg_token_broker/_usertoken.py +449 -0
  30. sg_token_broker-0.1.0/src/sg_token_broker/_verify.py +236 -0
  31. sg_token_broker-0.1.0/src/sg_token_broker/py.typed +0 -0
@@ -0,0 +1,46 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ dist/
13
+ .eggs/
14
+ *.egg-info/
15
+ *.egg
16
+
17
+ # Virtual environments
18
+ .venv/
19
+ venv/
20
+ ENV/
21
+
22
+ # PyInstaller
23
+ *.manifest
24
+ *.spec
25
+
26
+ # Unit test / coverage reports
27
+ htmlcov/
28
+ .tox/
29
+ .nox/
30
+ .coverage*
31
+ .pytest_cache/
32
+ .cache/
33
+
34
+ # Type checker / linter caches
35
+ .pyright/
36
+ .mypy_cache/
37
+ .ruff_cache/
38
+ pyrightconfig.json
39
+
40
+ # Editors
41
+ .vscode/
42
+ .idea/
43
+
44
+ # OS
45
+ .DS_Store
46
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 the sg-token-broker authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.5
2
+ Name: sg-token-broker
3
+ Version: 0.1.0
4
+ Summary: Authentication broker for Autodesk Flow Production Tracking
5
+ Project-URL: Documentation, https://github.com/dactylo/sg-token-broker/tree/main/docs
6
+ Project-URL: Homepage, https://github.com/dactylo/sg-token-broker
7
+ Project-URL: Issues, https://github.com/dactylo/sg-token-broker/issues
8
+ Project-URL: Repository, https://github.com/dactylo/sg-token-broker
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: authentication,credentials,flow-production-tracking,security,shotgrid,shotgun,token-broker
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Programming Language :: Python :: 3.15
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: pyyaml>=6.0.3
21
+ Requires-Dist: requests>=2.34.2
22
+ Requires-Dist: urllib3<3,>=1.26
23
+ Provides-Extra: google
24
+ Requires-Dist: cachecontrol>=0.14.4; extra == 'google'
25
+ Requires-Dist: google-auth>=2.3.2; extra == 'google'
26
+ Provides-Extra: login
27
+ Requires-Dist: keyring>=24; extra == 'login'
28
+ Provides-Extra: oidc
29
+ Requires-Dist: cryptography>=42; extra == 'oidc'
30
+ Requires-Dist: pyjwt<2.16,>=2.14; extra == 'oidc'
31
+ Description-Content-Type: text/markdown
32
+
33
+ # sg-token-broker
34
+
35
+ sg-token-broker lets pipeline tools call Autodesk Flow Production Tracking without receiving
36
+ long-lived API script keys. A service you run keeps the keys, checks each caller, and issues an SG
37
+ token with the permissions of a configured script account or of the signed-in person.
38
+
39
+ Use it when farm jobs, pipeline services, desktop tools, or Google Sheets need SG access and you
40
+ want to keep script keys on one host, limit which SG identities each caller can use, and record
41
+ every issuance in an audit log.
42
+
43
+ This documentation uses SG for Flow Production Tracking, formerly named Shotgun and ShotGrid.
44
+
45
+ ## Choose a service
46
+
47
+ Choose by whose permissions SG should enforce:
48
+
49
+ - **App-token broker:** for farm jobs, pipeline services, and shared tools. Each named *scope* maps
50
+ to an SG script account with a limited permission role, and each consuming system gets its own
51
+ broker credential.
52
+ - **User-token service:** for tools that act as the signed-in person. The service verifies the
53
+ person's studio sign-in and issues a token bound to their own SG account.
54
+
55
+ Both services issue REST tokens and session tokens. Existing `shotgun_api3` integrations need
56
+ session tokens, and user session tokens require a private deployment on a restricted network. See
57
+ [Choosing a credential](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/modes.md) for the tradeoffs.
58
+
59
+ ## Installation
60
+
61
+ You need Python 3.11 or later and [uv](https://docs.astral.sh/uv/). Running either service also
62
+ requires an SG site and an SG administrator who can create script accounts.
63
+
64
+ From a checkout of this repository, install the `sg-token-broker` command:
65
+
66
+ ```sh
67
+ uv tool install .
68
+ sg-token-broker --help
69
+ ```
70
+
71
+ After pulling changes, update it with `uv tool install --reinstall .`. The app-token broker and its
72
+ clients need no extras. Add an extra, as in `uv tool install '.[login]'`, for these features:
73
+
74
+ - `login`: stores a desktop sign-in in the operating system's keyring, so later commands do not
75
+ open a browser.
76
+ - `google`: lets the user-token service verify Google Workspace ID tokens.
77
+ - `oidc`: lets the user-token service verify ID tokens from another OIDC provider.
78
+
79
+ For Python integrations, install the package into the environment that runs your application, for
80
+ example with that environment's `python -m pip install /path/to/sg-token-broker`. The
81
+ `shotgun_api3` examples also need the SG Python API in that environment. A `uv tool` installation
82
+ does not make the library importable from other environments.
83
+
84
+ ## Quick start
85
+
86
+ This walkthrough runs the app-token broker on your machine and fetches a token for one scope. First
87
+ ask an SG administrator to create a script account, such as `broker_read_all`, whose permission
88
+ role grants only what your tool needs. Only the broker uses that account's application key.
89
+
90
+ ### Create a client credential
91
+
92
+ ```sh
93
+ sg-token-broker hash-secret
94
+ ```
95
+
96
+ The command prints a `secret:` line for the consuming tool and a `hash:` line for the broker
97
+ configuration. The broker stores only the hash.
98
+
99
+ ### Configure the broker
100
+
101
+ Save this as `broker.yml`, replacing the site URL and `secret_hash` with your values:
102
+
103
+ ```yaml
104
+ site_url: https://your-site.shotgrid.autodesk.com
105
+ server:
106
+ bind: 127.0.0.1
107
+ port: 8743
108
+ scopes:
109
+ read_all:
110
+ script_name: broker_read_all
111
+ script_key_env: SGTB_KEY_READ_ALL
112
+ clients:
113
+ farm_render:
114
+ secret_hash: paste-the-generated-hash-here
115
+ scopes: [read_all]
116
+ ```
117
+
118
+ The `read_all` scope maps to the `broker_read_all` script account, whose key the broker reads from
119
+ the `SGTB_KEY_READ_ALL` environment variable. The `farm_render` client may request only that scope.
120
+
121
+ ### Start the broker
122
+
123
+ Supply the script account's key, validate the configuration, and start the broker:
124
+
125
+ ```sh
126
+ export SGTB_KEY_READ_ALL='your-script-application-key'
127
+ sg-token-broker check-config --config broker.yml
128
+ sg-token-broker serve-app-tokens --config broker.yml
129
+ ```
130
+
131
+ `check-config` prints `ok: 1 scope(s), 1 client(s)`. The broker then reports
132
+ `serving on http://127.0.0.1:8743` and keeps running. It accepts plain HTTP here only because it
133
+ listens on loopback; any other address requires TLS.
134
+
135
+ ### Request a token
136
+
137
+ In another terminal, configure the client and request a token:
138
+
139
+ ```sh
140
+ export SG_TOKEN_BROKER_URL='http://127.0.0.1:8743'
141
+ export SG_TOKEN_BROKER_CLIENT_ID='farm_render'
142
+ export SG_TOKEN_BROKER_CLIENT_SECRET='the-generated-client-secret'
143
+ sg-token-broker get-token --scope read_all
144
+ ```
145
+
146
+ The command prints JSON with the SG session token in `token`, along with `token_type`, `scope`,
147
+ `site_url`, and `expires_at`. Add `--token-type rest` for a REST bearer token. Treat either token
148
+ as a credential. The broker's terminal shows one JSON `issue` record for the request, which
149
+ identifies the token without including it.
150
+
151
+ In Python, with this package and `shotgun_api3` installed in your application's environment:
152
+
153
+ ```python
154
+ import shotgun_api3
155
+
156
+ from sg_token_broker import BrokerClient
157
+
158
+ token = BrokerClient().fetch_token('read_all')
159
+ sg = shotgun_api3.Shotgun(token.site_url, session_token=token.token)
160
+ ```
161
+
162
+ `BrokerClient` reads the same three environment variables and reuses its token until shortly before
163
+ `expires_at`.
164
+
165
+ This setup listens only on your machine. Before shared use, follow the
166
+ [app-token broker deployment](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/deployment.md) guide for TLS, secret storage, and operations.
167
+ Session tokens stay valid while in use, and rotating a script key does not revoke them; read
168
+ [token lifetime and revocation](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/sg-token-behavior.md) before deploying.
169
+
170
+ ## Use the signed-in person's permissions
171
+
172
+ Deploy the [user-token service](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/user-token-service.md) for tools that need the caller's own SG
173
+ permissions. Choose the Cloud Run deployment for Google Workspace callers that use REST, or a
174
+ private deployment for session tokens used by `shotgun_api3`.
175
+
176
+ If your administrator already runs the service, start with
177
+ [desktop client setup](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/user-token-service.md#desktop-client-setup) or the
178
+ [Apps Script caller](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/user-token-service.md#apps-script-caller).
179
+
180
+ ## Documentation
181
+
182
+ | If you want to... | Read |
183
+ | ---------------------------------------------------------------- | --------------------------------------------------------------- |
184
+ | Choose between app and user tokens, or session and REST tokens | [Choosing a credential](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/modes.md) |
185
+ | Deploy, operate, or troubleshoot the app-token broker | [App-token broker deployment](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/deployment.md) |
186
+ | Deploy the user-token service | [User-token service](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/user-token-service.md) |
187
+ | Connect a desktop tool or Google Sheet to the user-token service | [Client setup](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/user-token-service.md#desktop-client-setup) |
188
+ | Handle token expiry or respond to a leaked credential | [Token lifetime and revocation](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/sg-token-behavior.md) |
189
+ | Understand the security boundaries and their limits | [Design and security](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/design.md) |
190
+ | See changes by version | [Changelog](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/CHANGELOG.md) |
191
+
192
+ ## Development
193
+
194
+ See the [development guide](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/docs/development.md) for the required tools, CI, and dependency locks.
195
+ With those tools installed, run:
196
+
197
+ ```sh
198
+ make setup
199
+ make check
200
+ ```
201
+
202
+ The checks use a local fake SG server and never contact a live site.
203
+
204
+ ## License
205
+
206
+ sg-token-broker is available under the [MIT License](https://github.com/dactylo/sg-token-broker/blob/v0.1.0/LICENSE). It is an independent project and is
207
+ not affiliated with or endorsed by Autodesk. Flow Production Tracking is a product of Autodesk,
208
+ Inc.
@@ -0,0 +1,176 @@
1
+ # sg-token-broker
2
+
3
+ sg-token-broker lets pipeline tools call Autodesk Flow Production Tracking without receiving
4
+ long-lived API script keys. A service you run keeps the keys, checks each caller, and issues an SG
5
+ token with the permissions of a configured script account or of the signed-in person.
6
+
7
+ Use it when farm jobs, pipeline services, desktop tools, or Google Sheets need SG access and you
8
+ want to keep script keys on one host, limit which SG identities each caller can use, and record
9
+ every issuance in an audit log.
10
+
11
+ This documentation uses SG for Flow Production Tracking, formerly named Shotgun and ShotGrid.
12
+
13
+ ## Choose a service
14
+
15
+ Choose by whose permissions SG should enforce:
16
+
17
+ - **App-token broker:** for farm jobs, pipeline services, and shared tools. Each named *scope* maps
18
+ to an SG script account with a limited permission role, and each consuming system gets its own
19
+ broker credential.
20
+ - **User-token service:** for tools that act as the signed-in person. The service verifies the
21
+ person's studio sign-in and issues a token bound to their own SG account.
22
+
23
+ Both services issue REST tokens and session tokens. Existing `shotgun_api3` integrations need
24
+ session tokens, and user session tokens require a private deployment on a restricted network. See
25
+ [Choosing a credential](docs/modes.md) for the tradeoffs.
26
+
27
+ ## Installation
28
+
29
+ You need Python 3.11 or later and [uv](https://docs.astral.sh/uv/). Running either service also
30
+ requires an SG site and an SG administrator who can create script accounts.
31
+
32
+ From a checkout of this repository, install the `sg-token-broker` command:
33
+
34
+ ```sh
35
+ uv tool install .
36
+ sg-token-broker --help
37
+ ```
38
+
39
+ After pulling changes, update it with `uv tool install --reinstall .`. The app-token broker and its
40
+ clients need no extras. Add an extra, as in `uv tool install '.[login]'`, for these features:
41
+
42
+ - `login`: stores a desktop sign-in in the operating system's keyring, so later commands do not
43
+ open a browser.
44
+ - `google`: lets the user-token service verify Google Workspace ID tokens.
45
+ - `oidc`: lets the user-token service verify ID tokens from another OIDC provider.
46
+
47
+ For Python integrations, install the package into the environment that runs your application, for
48
+ example with that environment's `python -m pip install /path/to/sg-token-broker`. The
49
+ `shotgun_api3` examples also need the SG Python API in that environment. A `uv tool` installation
50
+ does not make the library importable from other environments.
51
+
52
+ ## Quick start
53
+
54
+ This walkthrough runs the app-token broker on your machine and fetches a token for one scope. First
55
+ ask an SG administrator to create a script account, such as `broker_read_all`, whose permission
56
+ role grants only what your tool needs. Only the broker uses that account's application key.
57
+
58
+ ### Create a client credential
59
+
60
+ ```sh
61
+ sg-token-broker hash-secret
62
+ ```
63
+
64
+ The command prints a `secret:` line for the consuming tool and a `hash:` line for the broker
65
+ configuration. The broker stores only the hash.
66
+
67
+ ### Configure the broker
68
+
69
+ Save this as `broker.yml`, replacing the site URL and `secret_hash` with your values:
70
+
71
+ ```yaml
72
+ site_url: https://your-site.shotgrid.autodesk.com
73
+ server:
74
+ bind: 127.0.0.1
75
+ port: 8743
76
+ scopes:
77
+ read_all:
78
+ script_name: broker_read_all
79
+ script_key_env: SGTB_KEY_READ_ALL
80
+ clients:
81
+ farm_render:
82
+ secret_hash: paste-the-generated-hash-here
83
+ scopes: [read_all]
84
+ ```
85
+
86
+ The `read_all` scope maps to the `broker_read_all` script account, whose key the broker reads from
87
+ the `SGTB_KEY_READ_ALL` environment variable. The `farm_render` client may request only that scope.
88
+
89
+ ### Start the broker
90
+
91
+ Supply the script account's key, validate the configuration, and start the broker:
92
+
93
+ ```sh
94
+ export SGTB_KEY_READ_ALL='your-script-application-key'
95
+ sg-token-broker check-config --config broker.yml
96
+ sg-token-broker serve-app-tokens --config broker.yml
97
+ ```
98
+
99
+ `check-config` prints `ok: 1 scope(s), 1 client(s)`. The broker then reports
100
+ `serving on http://127.0.0.1:8743` and keeps running. It accepts plain HTTP here only because it
101
+ listens on loopback; any other address requires TLS.
102
+
103
+ ### Request a token
104
+
105
+ In another terminal, configure the client and request a token:
106
+
107
+ ```sh
108
+ export SG_TOKEN_BROKER_URL='http://127.0.0.1:8743'
109
+ export SG_TOKEN_BROKER_CLIENT_ID='farm_render'
110
+ export SG_TOKEN_BROKER_CLIENT_SECRET='the-generated-client-secret'
111
+ sg-token-broker get-token --scope read_all
112
+ ```
113
+
114
+ The command prints JSON with the SG session token in `token`, along with `token_type`, `scope`,
115
+ `site_url`, and `expires_at`. Add `--token-type rest` for a REST bearer token. Treat either token
116
+ as a credential. The broker's terminal shows one JSON `issue` record for the request, which
117
+ identifies the token without including it.
118
+
119
+ In Python, with this package and `shotgun_api3` installed in your application's environment:
120
+
121
+ ```python
122
+ import shotgun_api3
123
+
124
+ from sg_token_broker import BrokerClient
125
+
126
+ token = BrokerClient().fetch_token('read_all')
127
+ sg = shotgun_api3.Shotgun(token.site_url, session_token=token.token)
128
+ ```
129
+
130
+ `BrokerClient` reads the same three environment variables and reuses its token until shortly before
131
+ `expires_at`.
132
+
133
+ This setup listens only on your machine. Before shared use, follow the
134
+ [app-token broker deployment](docs/deployment.md) guide for TLS, secret storage, and operations.
135
+ Session tokens stay valid while in use, and rotating a script key does not revoke them; read
136
+ [token lifetime and revocation](docs/sg-token-behavior.md) before deploying.
137
+
138
+ ## Use the signed-in person's permissions
139
+
140
+ Deploy the [user-token service](docs/user-token-service.md) for tools that need the caller's own SG
141
+ permissions. Choose the Cloud Run deployment for Google Workspace callers that use REST, or a
142
+ private deployment for session tokens used by `shotgun_api3`.
143
+
144
+ If your administrator already runs the service, start with
145
+ [desktop client setup](docs/user-token-service.md#desktop-client-setup) or the
146
+ [Apps Script caller](docs/user-token-service.md#apps-script-caller).
147
+
148
+ ## Documentation
149
+
150
+ | If you want to... | Read |
151
+ | ---------------------------------------------------------------- | --------------------------------------------------------------- |
152
+ | Choose between app and user tokens, or session and REST tokens | [Choosing a credential](docs/modes.md) |
153
+ | Deploy, operate, or troubleshoot the app-token broker | [App-token broker deployment](docs/deployment.md) |
154
+ | Deploy the user-token service | [User-token service](docs/user-token-service.md) |
155
+ | Connect a desktop tool or Google Sheet to the user-token service | [Client setup](docs/user-token-service.md#desktop-client-setup) |
156
+ | Handle token expiry or respond to a leaked credential | [Token lifetime and revocation](docs/sg-token-behavior.md) |
157
+ | Understand the security boundaries and their limits | [Design and security](docs/design.md) |
158
+ | See changes by version | [Changelog](CHANGELOG.md) |
159
+
160
+ ## Development
161
+
162
+ See the [development guide](docs/development.md) for the required tools, CI, and dependency locks.
163
+ With those tools installed, run:
164
+
165
+ ```sh
166
+ make setup
167
+ make check
168
+ ```
169
+
170
+ The checks use a local fake SG server and never contact a live site.
171
+
172
+ ## License
173
+
174
+ sg-token-broker is available under the [MIT License](LICENSE). It is an independent project and is
175
+ not affiliated with or endorsed by Autodesk. Flow Production Tracking is a product of Autodesk,
176
+ Inc.
@@ -0,0 +1,171 @@
1
+ # ==========================================================
2
+ # Build System
3
+ # ==========================================================
4
+ [build-system]
5
+ build-backend = "hatchling.build"
6
+ requires = [ "editables~=0.3", "hatch-fancy-pypi-readme>=25.1", "hatchling>=1.27" ]
7
+
8
+ # ==========================================================
9
+ # Project Metadata
10
+ # ==========================================================
11
+ [project]
12
+ name = "sg-token-broker"
13
+ version = "0.1.0"
14
+ description = "Authentication broker for Autodesk Flow Production Tracking"
15
+ keywords = [
16
+ "authentication",
17
+ "credentials",
18
+ "flow-production-tracking",
19
+ "security",
20
+ "shotgrid",
21
+ "shotgun",
22
+ "token-broker"
23
+ ]
24
+ license = "MIT"
25
+ license-files = [ "LICENSE" ]
26
+ requires-python = ">=3.11"
27
+ classifiers = [
28
+ "Programming Language :: Python :: 3 :: Only",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Programming Language :: Python :: 3.13",
32
+ "Programming Language :: Python :: 3.14",
33
+ "Programming Language :: Python :: 3.15",
34
+ "Typing :: Typed",
35
+ ]
36
+ dynamic = [ "readme" ]
37
+ dependencies = [
38
+ "pyyaml>=6.0.3",
39
+ "requests>=2.34.2",
40
+ "urllib3>=1.26,<3",
41
+ ]
42
+ optional-dependencies.google = [
43
+ "cachecontrol>=0.14.4",
44
+ "google-auth>=2.3.2",
45
+ ]
46
+ optional-dependencies.login = [
47
+ "keyring>=24",
48
+ ]
49
+ optional-dependencies.oidc = [
50
+ "cryptography>=42",
51
+ "pyjwt>=2.14,<2.16", # _oidcverify overrides PyJWT internals; widen only after testing
52
+ ]
53
+ urls.Documentation = "https://github.com/dactylo/sg-token-broker/tree/main/docs"
54
+ urls.Homepage = "https://github.com/dactylo/sg-token-broker"
55
+ urls.Issues = "https://github.com/dactylo/sg-token-broker/issues"
56
+ urls.Repository = "https://github.com/dactylo/sg-token-broker"
57
+ scripts.sg-token-broker = "sg_token_broker._cli:main"
58
+
59
+ [dependency-groups]
60
+ dev = [
61
+ "mdformat",
62
+ "mdformat-config",
63
+ "mdformat-frontmatter",
64
+ "mdformat-gfm",
65
+ "mdformat-pyproject",
66
+ "mdformat-ruff",
67
+ "mdformat-shfmt",
68
+ "pyproject-fmt",
69
+ "pyright",
70
+ "ruff",
71
+ { include-group = "test" },
72
+ ]
73
+ test = [
74
+ "pytest",
75
+ "pytest-xdist>=3.2",
76
+ ]
77
+ ci-build = [
78
+ "cython>=3",
79
+ "setuptools>=84",
80
+ ]
81
+
82
+ [tool.hatch]
83
+ metadata.hooks.fancy-pypi-readme.content-type = "text/markdown"
84
+ metadata.hooks.fancy-pypi-readme.fragments = [ { path = "README.md" } ]
85
+ build.targets.wheel.packages = [ "src/sg_token_broker" ]
86
+ build.targets.sdist.include = [ "/README.md", "/src" ]
87
+
88
+ # Keep checkout links relative; package links target this release.
89
+ [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]]
90
+ pattern = '(!\[[^\]\n]*\]\()(?![A-Za-z][A-Za-z0-9+.-]*:|[/#])(?:\./)?([^\s)]+)(\))'
91
+ replacement = '\1https://raw.githubusercontent.com/dactylo/sg-token-broker/v$HFPR_VERSION/\2\3'
92
+
93
+ [[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]]
94
+ pattern = '(?<!!)(\[[^\]\n]+\]\()(?![A-Za-z][A-Za-z0-9+.-]*:|[/#])(?:\./)?([^\s)]+)(\))'
95
+ replacement = '\1https://github.com/dactylo/sg-token-broker/blob/v$HFPR_VERSION/\2\3'
96
+
97
+ [tool.uv]
98
+ # CI supplies native Taplo; mdformat-config 0.2.1 otherwise pulls a Python Taplo wheel.
99
+ exclude-dependencies = [
100
+ { package = { name = "mdformat-config", version = "0.2.1" }, dependencies = [ "taplo" ] },
101
+ ]
102
+
103
+ # ==========================================================
104
+ # Ruff Configuration
105
+ # ==========================================================
106
+ [tool.ruff]
107
+ target-version = "py311"
108
+ line-length = 99
109
+ format.quote-style = "single"
110
+ format.exclude = [ "*.md" ]
111
+ lint.select = [ "ALL" ]
112
+ lint.ignore = [
113
+ "COM812", # Conflicts with the Ruff formatter
114
+ "CPY001", # Copyright notices are not required
115
+ "EM101", # Exception must not use string literal
116
+ "EM102", # Exception must not use f-string literal
117
+ "FBT001", # Boolean positional arg in function definition
118
+ "FBT002", # Boolean default value in function definition
119
+ "Q000", # Conflicts with the Ruff formatter
120
+ "Q003", # Conflicts with the Ruff formatter
121
+ "T201", # print() found
122
+ "TRY003", # Avoid specifying long messages outside exception class
123
+ ]
124
+ # Same-file private-member collaboration; retain checking in other files.
125
+ lint.per-file-ignores."scripts/verify_sg_human_session.py" = [ "SLF001" ]
126
+ lint.per-file-ignores."scripts/verify_sg_sudo.py" = [ "SLF001" ]
127
+ lint.per-file-ignores."src/sg_token_broker/_cache.py" = [ "SLF001" ]
128
+ lint.per-file-ignores."src/sg_token_broker/_http.py" = [ "SLF001" ]
129
+ lint.per-file-ignores."src/sg_token_broker/_userauth.py" = [ "SLF001" ]
130
+ lint.per-file-ignores."src/sg_token_broker/_userhttp.py" = [ "SLF001" ]
131
+ lint.per-file-ignores."tests/**/*.py" = [
132
+ "D", # No docstrings required in tests
133
+ "PLR2004", # Allow magic values in tests
134
+ "S101", # Allow asserts in tests
135
+ "S603", # Allow subprocess calls in tests
136
+ "S607", # Allow partial executable paths in tests
137
+ "SLF001", # Tests intentionally inspect and patch private state
138
+ ]
139
+ lint.pydocstyle.convention = "google"
140
+
141
+ [tool.pyproject-fmt]
142
+ max_supported_python = "3.15"
143
+
144
+ # ==========================================================
145
+ # Pyright Configuration
146
+ # ==========================================================
147
+ [tool.pyright]
148
+ pythonVersion = "3.11" # Keep in sync with tool.ruff.target-version
149
+ typeCheckingMode = "strict"
150
+ extraPaths = [ ".", "src" ]
151
+ executionEnvironments = [
152
+ { root = "tests", reportPrivateUsage = "none" },
153
+ { root = "." },
154
+ ]
155
+
156
+ # ==========================================================
157
+ # Pytest Configuration
158
+ # ==========================================================
159
+ [tool.pytest]
160
+ ini_options.testpaths = [ "tests" ]
161
+ ini_options.pythonpath = [ "src" ]
162
+ ini_options.addopts = [ "-q", "--strict-markers", "--tb=short" ]
163
+ ini_options.markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')" ]
164
+ ini_options.faulthandler_timeout = 300
165
+
166
+ # ==========================================================
167
+ # Mdformat Configuration (Requires mdformat-pyproject)
168
+ # ==========================================================
169
+ [tool.mdformat]
170
+ wrap = 99 # Keep in sync with tool.ruff.line-length
171
+ number = true
@@ -0,0 +1,33 @@
1
+ """sg-token-broker: temporary, scoped, audited SG credentials.
2
+
3
+ The broker services hold master SG script keys and dispense SG session or REST
4
+ tokens to authenticated callers. REST tokens have a hard SG expiry, while
5
+ session tokens follow SG's sliding inactivity lifetime. Broker cache TTLs
6
+ govern token reuse; they do not define a session token's SG lifetime. This
7
+ package provides the services and their client libraries.
8
+
9
+ Use the `sg-token-broker` CLI to serve or request tokens. Python callers use
10
+ `BrokerClient` for app tokens or `UserTokenClient` for user tokens; their
11
+ settings come from `SG_TOKEN_BROKER_*` and `SG_USER_TOKEN_*` environment
12
+ variables, respectively.
13
+ """
14
+
15
+ from sg_token_broker._client import (
16
+ BrokerClient,
17
+ BrokerClientError,
18
+ ClientOptions,
19
+ TokenResponse,
20
+ fetch_token,
21
+ )
22
+ from sg_token_broker._userclient import UserToken, UserTokenClient, UserTokenClientError
23
+
24
+ __all__ = [
25
+ 'BrokerClient',
26
+ 'BrokerClientError',
27
+ 'ClientOptions',
28
+ 'TokenResponse',
29
+ 'UserToken',
30
+ 'UserTokenClient',
31
+ 'UserTokenClientError',
32
+ 'fetch_token',
33
+ ]
@@ -0,0 +1,8 @@
1
+ """Allow `python -m sg_token_broker`."""
2
+
3
+ import sys
4
+
5
+ from sg_token_broker._cli import main
6
+
7
+ if __name__ == '__main__':
8
+ sys.exit(main())