buildai-cli 0.3.44__tar.gz → 0.3.46__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. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/PKG-INFO +1 -1
  2. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/auth_local.py +10 -15
  3. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/context.py +27 -2
  4. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/ops_init.py +5 -3
  5. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/pyproject.toml +1 -1
  6. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/.gitignore +0 -0
  7. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/AGENTS.md +0 -0
  8. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/CLAUDE.md +0 -0
  9. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/buildai_bootstrap.py +0 -0
  10. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/__init__.py +0 -0
  11. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/_has_core.py +0 -0
  12. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/__init__.py +0 -0
  13. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/api_proxy.py +0 -0
  14. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/auth.py +0 -0
  15. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/db/__init__.py +0 -0
  16. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/db/common.py +0 -0
  17. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/db/migrate.py +0 -0
  18. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/db/query.py +0 -0
  19. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/db/schema.py +0 -0
  20. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/db/status.py +0 -0
  21. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/dev.py +0 -0
  22. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/commands/doctor.py +0 -0
  23. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/config.py +0 -0
  24. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/console.py +0 -0
  25. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/guard.py +0 -0
  26. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/internal_api.py +0 -0
  27. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/main.py +0 -0
  28. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/nl_query/__init__.py +0 -0
  29. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/nl_query/dataset_tools.py +0 -0
  30. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/output.py +0 -0
  31. {buildai_cli-0.3.44 → buildai_cli-0.3.46}/cli/pagination.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: buildai-cli
3
- Version: 0.3.44
3
+ Version: 0.3.46
4
4
  Summary: Build AI CLI (Typer)
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: python-dotenv>=1.0.0
@@ -95,18 +95,12 @@ class ResolvedLocalAuthProfile:
95
95
  f'export ALLOYDB_IAM_AUTH_{suffix}="true"',
96
96
  ]
97
97
  )
98
- if self.name == "engineers-dev":
99
- exports.extend(
100
- [
101
- f'export ALLOYDB_USE_AUTH_PROXY_{suffix}="true"',
102
- 'export ALLOYDB_AUTH_PROXY_HOST="127.0.0.1"',
103
- f'export ALLOYDB_AUTH_PROXY_PORT_{suffix}="5440"',
104
- ]
105
- )
106
- else:
107
- exports.append(
108
- f'export ALLOYDB_RUNTIME_IMPERSONATE_SA_{suffix}="{self.target_service_account}"'
109
- )
98
+ exports.extend(
99
+ [
100
+ f'export ALLOYDB_RUNTIME_IMPERSONATE_SA_{suffix}="{self.target_service_account}"',
101
+ f'export ALLOYDB_USE_AUTH_PROXY_{suffix}="false"',
102
+ ]
103
+ )
110
104
  elif self.name == "db-admin-local" and self.target_db_user and self.target_service_account:
111
105
  exports.extend(
112
106
  [
@@ -200,10 +194,11 @@ def sanctioned_auth_profiles() -> tuple[LocalAuthProfile, ...]:
200
194
  LocalAuthProfile(
201
195
  name="engineers-dev",
202
196
  audience="engineers",
203
- summary="Use the engineer-facing read-only DB and operator lane.",
197
+ summary="Use the engineer-facing read-only DB lane.",
204
198
  purpose=(
205
- "Use this for direct CLI database reads, schema inspection, and desktop SQL "
206
- "tooling. Local API runtime parity should use the service-runtime profiles instead."
199
+ "Use this for direct CLI database reads and schema inspection through the "
200
+ "engineer-facing service-account identity. Local API runtime parity should "
201
+ "use the service-runtime profiles instead."
207
202
  ),
208
203
  ),
209
204
  LocalAuthProfile(
@@ -22,6 +22,7 @@ from dataclasses import dataclass
22
22
  from typing import TYPE_CHECKING, AsyncGenerator
23
23
 
24
24
  import asyncpg
25
+ from dal import scopes as dal_scopes
25
26
  from infra.settings import Settings, get_settings
26
27
 
27
28
  from infra import Database, get_logger
@@ -34,6 +35,22 @@ logger = get_logger(__name__)
34
35
  # Environment variable to force local PostgreSQL (for test/CI)
35
36
  USE_LOCAL_DB = os.getenv("USE_LOCAL_DB", "false").lower() == "true"
36
37
  _ZERO_UUID = "00000000-0000-0000-0000-000000000000"
38
+ _READ_SUFFIXES = (".read", ".search", ".query", ".introspection")
39
+ _READ_PROFILE_SCOPES = frozenset(
40
+ scope
41
+ for scope in dal_scopes.ALL_SCOPES
42
+ if any(scope.endswith(suffix) for suffix in _READ_SUFFIXES)
43
+ )
44
+ _CLI_PROFILE_SCOPES: dict[str, frozenset[str]] = {
45
+ "internal_admin": frozenset(dal_scopes.ALL_SCOPES),
46
+ "internal_viewer": _READ_PROFILE_SCOPES,
47
+ "engineers-dev": _READ_PROFILE_SCOPES,
48
+ "developer": frozenset(dal_scopes.ALL_SCOPES),
49
+ "operator": frozenset(dal_scopes.ALL_SCOPES),
50
+ "ml_engineer": frozenset(dal_scopes.ALL_SCOPES),
51
+ "mcp": _READ_PROFILE_SCOPES,
52
+ "agent": frozenset(dal_scopes.ALL_SCOPES),
53
+ }
37
54
  _UNRESTRICTED_CLI_PROFILES = frozenset(
38
55
  {
39
56
  "internal_admin",
@@ -47,6 +64,14 @@ _UNRESTRICTED_CLI_PROFILES = frozenset(
47
64
  )
48
65
 
49
66
 
67
+ def scopes_for_cli_profile(profile: str) -> frozenset[str]:
68
+ """Resolve one sanctioned CLI profile to its DAL scope set."""
69
+ resolved = _CLI_PROFILE_SCOPES.get(profile)
70
+ if resolved is None:
71
+ raise ValueError(f"Unknown CLI profile: {profile}")
72
+ return resolved
73
+
74
+
50
75
  @dataclass(frozen=True)
51
76
  class AdminConnectionConfig:
52
77
  """Describe the canonical admin connection the ops-plane CLI should prefer.
@@ -281,7 +306,7 @@ async def get_cli_context(
281
306
  # Test/CI: wrap local connection in context
282
307
  async with _local_connection(settings) as conn:
283
308
  await _stamp_cli_session_contract(conn, profile=resolved_profile)
284
- ctx = await Context.for_cli_profile(conn, profile=resolved_profile)
309
+ ctx = Context.for_cli(conn, scopes=scopes_for_cli_profile(resolved_profile))
285
310
  yield None, ctx
286
311
  else:
287
312
  # Development/Production: use infra.Database
@@ -289,7 +314,7 @@ async def get_cli_context(
289
314
  try:
290
315
  await db.connect()
291
316
  await _stamp_cli_session_contract(db.conn, profile=resolved_profile)
292
- ctx = await Context.for_cli_profile(db, profile=resolved_profile)
317
+ ctx = Context.for_cli(db, scopes=scopes_for_cli_profile(resolved_profile))
293
318
  yield db, ctx
294
319
  finally:
295
320
  await db.close()
@@ -34,11 +34,12 @@ def _parse_env(value: str) -> str:
34
34
 
35
35
 
36
36
  def _auth_env_prefix(settings_app_env: object) -> str:
37
- if str(settings_app_env) == "production":
37
+ normalized = str(getattr(settings_app_env, "value", settings_app_env)).strip().lower()
38
+ if normalized == "production":
38
39
  return "PROD"
39
- if str(settings_app_env) == "development":
40
+ if normalized == "development":
40
41
  return "DEV"
41
- if str(settings_app_env) == "test":
42
+ if normalized == "test":
42
43
  return "DEV"
43
44
  return "PREVIEW"
44
45
 
@@ -160,6 +161,7 @@ def init_ops_context(ctx: typer.Context):
160
161
  os.environ[f"ALLOYDB_RUNTIME_IMPERSONATE_SA_{env_prefix}"] = (
161
162
  "engineers-dev-sa@data-470400.iam.gserviceaccount.com"
162
163
  )
164
+ os.environ[f"ALLOYDB_USE_AUTH_PROXY_{env_prefix}"] = "false"
163
165
  auth_info.append("impersonate=engineers-dev-sa")
164
166
 
165
167
  # Reload settings with overrides
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "buildai-cli"
7
- version = "0.3.44"
7
+ version = "0.3.46"
8
8
  description = "Build AI CLI (Typer)"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes