svc-infra 0.1.618__py3-none-any.whl → 0.1.620__py3-none-any.whl

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.

Potentially problematic release.


This version of svc-infra might be problematic. Click here for more details.

@@ -50,9 +50,19 @@ class SimpleRateLimitMiddleware(BaseHTTPMiddleware):
50
50
  tenant_id = await _resolve_tenant_id(request)
51
51
  except Exception:
52
52
  tenant_id = None
53
- # Fallback: read from header only if explicitly trusted
54
- if not tenant_id and self._allow_untrusted_tenant_header:
55
- tenant_id = request.headers.get("X-Tenant-Id") or request.headers.get("X-Tenant-ID")
53
+ # Fallback header behavior:
54
+ # - If tenancy context is unavailable (minimal builds), accept header by default so
55
+ # unit/integration tests can exercise per-tenant scoping without full auth state.
56
+ # - If tenancy is available, only trust the header when explicitly allowed.
57
+ if not tenant_id:
58
+ if _resolve_tenant_id is None:
59
+ tenant_id = request.headers.get("X-Tenant-Id") or request.headers.get(
60
+ "X-Tenant-ID"
61
+ )
62
+ elif self._allow_untrusted_tenant_header:
63
+ tenant_id = request.headers.get("X-Tenant-Id") or request.headers.get(
64
+ "X-Tenant-ID"
65
+ )
56
66
 
57
67
  key = self.key_fn(request)
58
68
  if self.scope_by_tenant and tenant_id:
svc_infra/cli/__init__.py CHANGED
@@ -20,17 +20,23 @@ from svc_infra.cli.foundation.typer_bootstrap import pre_cli
20
20
  app = typer.Typer(no_args_is_help=True, add_completion=False, help=_HELP)
21
21
  pre_cli(app)
22
22
 
23
- # --- sql commands ---
24
- register_alembic(app)
25
- register_sql_scaffold(app)
26
- register_sql_export(app)
27
-
28
- # --- nosql commands ---
29
- register_mongo(app)
30
- register_mongo_scaffold(app)
31
-
32
- # -- observability commands ---
33
- register_obs(app)
23
+ # --- sql group ---
24
+ sql_app = typer.Typer(no_args_is_help=True, add_completion=False, help="SQL commands")
25
+ register_alembic(sql_app)
26
+ register_sql_scaffold(sql_app)
27
+ register_sql_export(sql_app)
28
+ app.add_typer(sql_app, name="sql")
29
+
30
+ # --- mongo group ---
31
+ mongo_app = typer.Typer(no_args_is_help=True, add_completion=False, help="MongoDB commands")
32
+ register_mongo(mongo_app)
33
+ register_mongo_scaffold(mongo_app)
34
+ app.add_typer(mongo_app, name="mongo")
35
+
36
+ # -- obs group ---
37
+ obs_app = typer.Typer(no_args_is_help=True, add_completion=False, help="Observability commands")
38
+ register_obs(obs_app)
39
+ app.add_typer(obs_app, name="obs")
34
40
 
35
41
  # -- dx commands ---
36
42
  register_dx(app)
@@ -188,6 +188,7 @@ def cmd_ping(
188
188
 
189
189
 
190
190
  def register(app: typer.Typer) -> None:
191
- app.command("mongo-prepare")(cmd_prepare)
192
- app.command("mongo-setup-and-prepare")(cmd_setup_and_prepare)
193
- app.command("mongo-ping")(cmd_ping)
191
+ # Attach to 'mongo' group app
192
+ app.command("prepare")(cmd_prepare)
193
+ app.command("setup-and-prepare")(cmd_setup_and_prepare)
194
+ app.command("ping")(cmd_ping)
@@ -127,7 +127,7 @@ def register(app: typer.Typer) -> None:
127
127
  • mongo-scaffold-schemas
128
128
  • mongo-scaffold-resources
129
129
  """
130
- app.command("mongo-scaffold")(cmd_scaffold)
131
- app.command("mongo-scaffold-documents")(cmd_scaffold_documents)
132
- app.command("mongo-scaffold-schemas")(cmd_scaffold_schemas)
133
- app.command("mongo-scaffold-resources")(cmd_scaffold_resources)
130
+ app.command("scaffold")(cmd_scaffold)
131
+ app.command("scaffold-documents")(cmd_scaffold_documents)
132
+ app.command("scaffold-schemas")(cmd_scaffold_schemas)
133
+ app.command("scaffold-resources")(cmd_scaffold_resources)
@@ -201,16 +201,17 @@ def cmd_setup_and_migrate(
201
201
 
202
202
 
203
203
  def register(app: typer.Typer) -> None:
204
- app.command("sql-init")(cmd_init)
205
- app.command("sql-revision")(cmd_revision)
206
- app.command("sql-upgrade")(cmd_upgrade)
207
- app.command("sql-downgrade")(cmd_downgrade)
208
- app.command("sql-current")(cmd_current)
209
- app.command("sql-history")(cmd_history)
210
- app.command("sql-stamp")(cmd_stamp)
211
- app.command("sql-merge-heads")(cmd_merge_heads)
212
- app.command("sql-setup-and-migrate")(cmd_setup_and_migrate)
213
- app.command("sql-seed")(cmd_seed)
204
+ # Register under the 'sql' group app
205
+ app.command("init")(cmd_init)
206
+ app.command("revision")(cmd_revision)
207
+ app.command("upgrade")(cmd_upgrade)
208
+ app.command("downgrade")(cmd_downgrade)
209
+ app.command("current")(cmd_current)
210
+ app.command("history")(cmd_history)
211
+ app.command("stamp")(cmd_stamp)
212
+ app.command("merge-heads")(cmd_merge_heads)
213
+ app.command("setup-and-migrate")(cmd_setup_and_migrate)
214
+ app.command("seed")(cmd_seed)
214
215
 
215
216
 
216
217
  def _import_callable(path: str):
@@ -17,10 +17,7 @@ try: # SQLAlchemy async extras are optional
17
17
  except Exception: # pragma: no cover - fallback when async extras unavailable
18
18
  AsyncEngine = None # type: ignore[assignment]
19
19
 
20
- app = typer.Typer(help="SQL data export commands")
21
20
 
22
-
23
- @app.command("export-tenant")
24
21
  def export_tenant(
25
22
  table: str = typer.Argument(..., help="Qualified table name to export (e.g., public.items)"),
26
23
  tenant_id: str = typer.Option(..., "--tenant-id", help="Tenant id value to filter by."),
@@ -79,4 +76,5 @@ def export_tenant(
79
76
 
80
77
 
81
78
  def register(app_root: typer.Typer) -> None:
82
- app_root.add_typer(app, name="sql")
79
+ # Attach directly to the provided 'sql' group app
80
+ app_root.command("export-tenant")(export_tenant)
@@ -134,6 +134,6 @@ def cmd_scaffold_schemas(
134
134
 
135
135
 
136
136
  def register(app: typer.Typer) -> None:
137
- app.command("sql-scaffold")(cmd_scaffold)
138
- app.command("sql-scaffold-models")(cmd_scaffold_models)
139
- app.command("sql-scaffold-schemas")(cmd_scaffold_schemas)
137
+ app.command("scaffold")(cmd_scaffold)
138
+ app.command("scaffold-models")(cmd_scaffold_models)
139
+ app.command("scaffold-schemas")(cmd_scaffold_schemas)
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import importlib.util
3
4
  import os
4
5
  from importlib.metadata import PackageNotFoundError, distribution
5
6
  from pathlib import Path
@@ -24,31 +25,50 @@ def _discover_fs_topics(docs_dir: Path) -> Dict[str, Path]:
24
25
  def _discover_pkg_topics() -> Dict[str, Path]:
25
26
  """Discover docs packaged under 'docs/' in the installed distribution.
26
27
 
27
- This lets 'svc-infra docs' work from external projects that don't have a
28
- local docs/ directory by falling back to files shipped in the wheel.
28
+ Works in external projects without a local docs/ by inspecting the wheel
29
+ metadata and, as a fallback, searching for a top-level docs/ next to the
30
+ installed package directory in site-packages.
29
31
  """
30
32
  topics: Dict[str, Path] = {}
31
- try:
32
- dist = distribution("svc-infra")
33
- except PackageNotFoundError:
34
- return topics
35
-
36
- files = getattr(dist, "files", None) or []
37
- for f in files:
38
- # f is a PackagePath; string form like 'docs/topic.md'
39
- s = str(f)
40
- if not s.startswith("docs/") or not s.endswith(".md"):
41
- continue
42
- name = Path(s).stem.replace(" ", "-")
33
+
34
+ # 1) Prefer distribution metadata (RECORD) for both hyphen/underscore names
35
+ dist = None
36
+ for name in ("svc-infra", "svc_infra"):
43
37
  try:
44
- abs_path = dist.locate_file(f)
45
- # Ensure it's a file before adding
46
- abs_p = Path(abs_path)
47
- if abs_p.exists() and abs_p.is_file():
48
- topics[name] = abs_p
49
- except Exception:
50
- # best-effort; skip unreadable entries
51
- continue
38
+ dist = distribution(name)
39
+ break
40
+ except PackageNotFoundError:
41
+ dist = None
42
+
43
+ if dist is not None:
44
+ files = getattr(dist, "files", None) or []
45
+ for f in files:
46
+ s = str(f)
47
+ if not s.startswith("docs/") or not s.endswith(".md"):
48
+ continue
49
+ topic_name = Path(s).stem.replace(" ", "-")
50
+ try:
51
+ abs_path = Path(dist.locate_file(f))
52
+ if abs_path.exists() and abs_path.is_file():
53
+ topics[topic_name] = abs_path
54
+ except Exception:
55
+ # Best effort; continue to next
56
+ continue
57
+
58
+ # 2) Fallback: site-packages sibling 'docs/' directory
59
+ try:
60
+ spec = importlib.util.find_spec("svc_infra")
61
+ if spec and spec.submodule_search_locations:
62
+ pkg_dir = Path(next(iter(spec.submodule_search_locations)))
63
+ candidate = pkg_dir.parent / "docs"
64
+ if candidate.exists() and candidate.is_dir():
65
+ for p in sorted(candidate.glob("*.md")):
66
+ if p.is_file():
67
+ topics.setdefault(p.stem.replace(" ", "-"), p)
68
+ except Exception:
69
+ # Optional fallback only
70
+ pass
71
+
52
72
  return topics
53
73
 
54
74
 
@@ -57,19 +77,21 @@ def _resolve_docs_dir(ctx: click.Context) -> Path | None:
57
77
  # executes subcommands in child contexts that do not inherit params.
58
78
  current: click.Context | None = ctx
59
79
  while current is not None:
60
- docs_dir = (current.params or {}).get("docs_dir")
61
- if docs_dir:
62
- path = docs_dir if isinstance(docs_dir, Path) else Path(docs_dir)
80
+ docs_dir_opt = (current.params or {}).get("docs_dir")
81
+ if docs_dir_opt:
82
+ path = docs_dir_opt if isinstance(docs_dir_opt, Path) else Path(docs_dir_opt)
63
83
  path = path.expanduser()
64
84
  if path.exists():
65
85
  return path
66
86
  current = current.parent
87
+
67
88
  # Env var next
68
89
  env_dir = os.getenv("SVC_INFRA_DOCS_DIR")
69
90
  if env_dir:
70
91
  p = Path(env_dir).expanduser()
71
92
  if p.exists():
72
93
  return p
94
+
73
95
  # Project docs
74
96
  root = resolve_project_root()
75
97
  proj_docs = root / "docs"
@@ -88,16 +110,15 @@ class DocsGroup(TyperGroup):
88
110
  names.extend([k for k in fs.keys()])
89
111
  names.extend([k for k in pkg.keys() if k not in fs])
90
112
  # Deduplicate and sort
91
- uniq = sorted({*names})
92
- return uniq
113
+ return sorted({*names})
93
114
 
94
115
  def get_command(self, ctx: click.Context, name: str) -> click.Command | None:
95
- # Built-ins first (e.g., list)
116
+ # Built-ins first (e.g., list, show)
96
117
  cmd = super().get_command(ctx, name)
97
118
  if cmd is not None:
98
119
  return cmd
99
120
 
100
- # Dynamic topic resolution
121
+ # Dynamic topic resolution from FS
101
122
  dir_to_use = _resolve_docs_dir(ctx)
102
123
  fs = _discover_fs_topics(dir_to_use) if dir_to_use else {}
103
124
  if name in fs:
@@ -145,6 +166,10 @@ def register(app: typer.Typer) -> None:
145
166
  if topic in fs:
146
167
  typer.echo(fs[topic].read_text(encoding="utf-8", errors="replace"))
147
168
  raise typer.Exit(code=0)
169
+ pkg = _discover_pkg_topics()
170
+ if topic in pkg:
171
+ typer.echo(pkg[topic].read_text(encoding="utf-8", errors="replace"))
172
+ raise typer.Exit(code=0)
148
173
  raise typer.BadParameter(f"Unknown topic: {topic}")
149
174
 
150
175
  @docs_app.command("list", help="List available documentation topics")
@@ -182,6 +182,7 @@ def scaffold(target: str = typer.Option(..., help="compose|railway|k8s|fly")):
182
182
 
183
183
 
184
184
  def register(app: typer.Typer) -> None:
185
- app.command("obs-up")(up)
186
- app.command("obs-down")(down)
187
- app.command("obs-scaffold")(scaffold)
185
+ # Attach to 'obs' group app
186
+ app.command("up")(up)
187
+ app.command("down")(down)
188
+ app.command("scaffold")(scaffold)
@@ -29,17 +29,17 @@ We provide four CLI commands. You can register them on your Typer app or invoke
29
29
 
30
30
  ### Commands
31
31
 
32
- - `mongo-scaffold` — create both document **and** CRUD schemas
33
- - `mongo-scaffold-documents` — create only the **document** model (Pydantic)
34
- - `mongo-scaffold-schemas` — create only the **CRUD schemas**
35
- - `mongo-scaffold-resources` — create a starter `resources.py` with a `RESOURCES` list
32
+ - `mongo scaffold` — create both document **and** CRUD schemas
33
+ - `mongo scaffold-documents` — create only the **document** model (Pydantic)
34
+ - `mongo scaffold-schemas` — create only the **CRUD schemas**
35
+ - `mongo scaffold-resources` — create a starter `resources.py` with a `RESOURCES` list
36
36
 
37
37
  ### Typical usage
38
38
 
39
39
  #### A) Scaffold documents + schemas together
40
40
 
41
41
  ```bash
42
- yourapp mongo-scaffold \
42
+ yourapp mongo scaffold \
43
43
  --entity-name Product \
44
44
  --documents-dir ./src/your_app/products \
45
45
  --schemas-dir ./src/your_app/products \
@@ -57,7 +57,7 @@ src/your_app/products/schemas.py # ProductRead/ProductCreate/ProductUpdate
57
57
  B) Documents only
58
58
 
59
59
  ```bash
60
- yourapp mongo-scaffold-documents \
60
+ yourapp mongo scaffold-documents \
61
61
  --dest-dir ./src/your_app/products \
62
62
  --entity-name Product \
63
63
  --documents-filename product_doc.py
@@ -66,7 +66,7 @@ yourapp mongo-scaffold-documents \
66
66
  C) Schemas only
67
67
 
68
68
  ```bash
69
- yourapp mongo-scaffold-schemas \
69
+ yourapp mongo scaffold-schemas \
70
70
  --dest-dir ./src/your_app/products \
71
71
  --entity-name Product \
72
72
  --schemas-filename product_schemas.py
@@ -75,7 +75,7 @@ yourapp mongo-scaffold-schemas \
75
75
  D) Starter resources.py
76
76
 
77
77
  ```bash
78
- yourapp mongo-scaffold-resources \
78
+ yourapp mongo scaffold-resources \
79
79
  --dest-dir ./src/your_app/mongo \
80
80
  --filename resources.py \
81
81
  --overwrite
@@ -131,7 +131,7 @@ There are two flavors:
131
131
  A) Async, minimal (connect, create collections, apply indexes)
132
132
 
133
133
  ```bash
134
- yourapp mongo-prepare \
134
+ yourapp mongo prepare \
135
135
  --resources your_app.mongo.resources:RESOURCES \
136
136
  --mongo-url "$MONGO_URL" \
137
137
  --mongo-db "$MONGO_DB"
@@ -140,7 +140,7 @@ yourapp mongo-prepare \
140
140
  B) Synchronous wrapper (end-to-end convenience)
141
141
 
142
142
  ```bash
143
- yourapp mongo-setup-and-prepare \
143
+ yourapp mongo setup-and-prepare \
144
144
  --resources your_app.mongo.resources:RESOURCES \
145
145
  --mongo-url "$MONGO_URL" \
146
146
  --mongo-db "$MONGO_DB"
@@ -149,7 +149,7 @@ yourapp mongo-setup-and-prepare \
149
149
  You can also ping connectivity:
150
150
 
151
151
  ```bash
152
- yourapp mongo-ping --mongo-url "$MONGO_URL" --mongo-db "$MONGO_DB"
152
+ yourapp mongo ping --mongo-url "$MONGO_URL" --mongo-db "$MONGO_DB"
153
153
  ```
154
154
 
155
155
  Behind the scenes, preparation also locks a service ID to a DB name to prevent accidental cross-DB usage. You can pass --allow-rebind if you intentionally move environments.
@@ -430,9 +430,9 @@ NoSqlResource(
430
430
  • If using explicit schemas with PyObjectId, make sure model_config.json_encoders includes {PyObjectId: str}.
431
431
  • When using auto-schemas, we expose ObjectId-like fields as str so no custom encoder is needed.
432
432
  • Connected to wrong DB name
433
- • The system locks a service_id to the DB name once prepared. If you change DBs, run mongo-prepare with --allow-rebind.
433
+ • The system locks a service_id to the DB name once prepared. If you change DBs, run `mongo prepare` with --allow-rebind.
434
434
  • Indexes not created
435
- • Double-check RESOURCES[indexes]. Run mongo-prepare again and inspect the output dictionary of created indexes.
435
+ • Double-check RESOURCES[indexes]. Run `mongo prepare` again and inspect the output dictionary of created indexes.
436
436
 
437
437
 
438
438
 
@@ -3,6 +3,8 @@ from __future__ import annotations
3
3
  from enum import Enum
4
4
 
5
5
  from ai_infra.llm.tools.custom.cli import cli_cmd_help, cli_subcmd_help
6
+ from svc_infra.app.env import prepare_env
7
+ from svc_infra.cli.foundation.runner import run_from_root
6
8
  from ai_infra.mcp.server.tools import mcp_from_functions
7
9
 
8
10
  CLI_PROG = "svc-infra"
@@ -18,33 +20,34 @@ async def svc_infra_cmd_help() -> dict:
18
20
 
19
21
 
20
22
  class Subcommand(str, Enum):
21
- # SQL commands
22
- sql_init = "sql-init"
23
- sql_revision = "sql-revision"
24
- sql_upgrade = "sql-upgrade"
25
- sql_downgrade = "sql-downgrade"
26
- sql_current = "sql-current"
27
- sql_history = "sql-history"
28
- sql_stamp = "sql-stamp"
29
- sql_merge_heads = "sql-merge-heads"
30
- sql_setup_and_migrate = "sql-setup-and-migrate"
31
- sql_scaffold = "sql-scaffold"
32
- sql_scaffold_models = "sql-scaffold-models"
33
- sql_scaffold_schemas = "sql-scaffold-schemas"
23
+ # SQL group commands
24
+ sql_init = "sql init"
25
+ sql_revision = "sql revision"
26
+ sql_upgrade = "sql upgrade"
27
+ sql_downgrade = "sql downgrade"
28
+ sql_current = "sql current"
29
+ sql_history = "sql history"
30
+ sql_stamp = "sql stamp"
31
+ sql_merge_heads = "sql merge-heads"
32
+ sql_setup_and_migrate = "sql setup-and-migrate"
33
+ sql_scaffold = "sql scaffold"
34
+ sql_scaffold_models = "sql scaffold-models"
35
+ sql_scaffold_schemas = "sql scaffold-schemas"
36
+ sql_export_tenant = "sql export-tenant"
34
37
 
35
- # Mongo commands
36
- mongo_prepare = "mongo-prepare"
37
- mongo_setup_and_prepare = "mongo-setup-and-prepare"
38
- mongo_ping = "mongo-ping"
39
- mongo_scaffold = "mongo-scaffold"
40
- mongo_scaffold_documents = "mongo-scaffold-documents"
41
- mongo_scaffold_schemas = "mongo-scaffold-schemas"
42
- mongo_scaffold_resources = "mongo-scaffold-resources"
38
+ # Mongo group commands
39
+ mongo_prepare = "mongo prepare"
40
+ mongo_setup_and_prepare = "mongo setup-and-prepare"
41
+ mongo_ping = "mongo ping"
42
+ mongo_scaffold = "mongo scaffold"
43
+ mongo_scaffold_documents = "mongo scaffold-documents"
44
+ mongo_scaffold_schemas = "mongo scaffold-schemas"
45
+ mongo_scaffold_resources = "mongo scaffold-resources"
43
46
 
44
- # Observability commands
45
- obs_up = "obs-up"
46
- obs_down = "obs-down"
47
- obs_scaffold = "obs-scaffold"
47
+ # Observability group commands
48
+ obs_up = "obs up"
49
+ obs_down = "obs down"
50
+ obs_scaffold = "obs scaffold"
48
51
 
49
52
 
50
53
  async def svc_infra_subcmd_help(subcommand: Subcommand) -> dict:
@@ -52,7 +55,19 @@ async def svc_infra_subcmd_help(subcommand: Subcommand) -> dict:
52
55
  Get help text for a specific subcommand of svc-infra CLI.
53
56
  (Enum keeps a tight schema; function signature remains simple.)
54
57
  """
55
- return await cli_subcmd_help(CLI_PROG, subcommand)
58
+ tokens = subcommand.value.split()
59
+ if len(tokens) == 1:
60
+ return await cli_subcmd_help(CLI_PROG, subcommand)
61
+
62
+ root = prepare_env()
63
+ text = await run_from_root(root, CLI_PROG, [*tokens, "--help"])
64
+ return {
65
+ "ok": True,
66
+ "action": "subcommand_help",
67
+ "subcommand": subcommand.value,
68
+ "project_root": str(root),
69
+ "help": text,
70
+ }
56
71
 
57
72
 
58
73
  mcp = mcp_from_functions(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: svc-infra
3
- Version: 0.1.618
3
+ Version: 0.1.620
4
4
  Summary: Infrastructure for building and deploying prod-ready services
5
5
  License: MIT
6
6
  Keywords: fastapi,sqlalchemy,alembic,auth,infra,async,pydantic
@@ -80,7 +80,7 @@ svc_infra/api/fastapi/middleware/errors/handlers.py,sha256=pQMVs5n627vcKkDFEaUzx
80
80
  svc_infra/api/fastapi/middleware/idempotency.py,sha256=vnBQgMWzJVaF8oWgfw2ATjEKCyQifDeGPUc9z1N7ebE,5051
81
81
  svc_infra/api/fastapi/middleware/idempotency_store.py,sha256=BQN_Cq_jf_cuZRhze4EF5v0lOMQXpUWoRo7CsSTprug,5528
82
82
  svc_infra/api/fastapi/middleware/optimistic_lock.py,sha256=9lOMBI4VNIVndXnrMmgSq4qeR7xPjNR1H9d1F71M5S8,1271
83
- svc_infra/api/fastapi/middleware/ratelimit.py,sha256=f-nvsh3wqLMpDEmwPsKvVnOrM3cfC9AqQyl8eUqrUQM,4496
83
+ svc_infra/api/fastapi/middleware/ratelimit.py,sha256=Zw55_vlSVz4aqwr7gZ1P53HHZMO6fYUUQ7TXBzjEbw8,5014
84
84
  svc_infra/api/fastapi/middleware/ratelimit_store.py,sha256=LmJR8-kkW42rzOjls9lG1SBtCKjVY7L2Y_bNKHNY3-A,2553
85
85
  svc_infra/api/fastapi/middleware/request_id.py,sha256=Iru7ypTdK_n76lwziEGDWoVF4FKS0Ps1PMASYmzK8ek,768
86
86
  svc_infra/api/fastapi/middleware/request_size_limit.py,sha256=AcGqaB-F7Tbhg-at7ViT4Bpifst34jFneDBlUBjgo5I,1248
@@ -129,27 +129,27 @@ svc_infra/cache/resources.py,sha256=BhvPAZvCQ-fitUdniGEOOE4g1ZvljdCA_R5pR8WfJz4,
129
129
  svc_infra/cache/tags.py,sha256=9URw4BRlnb4QFAYpDI36fMms6642xq4TeV9jqsEjzE8,2625
130
130
  svc_infra/cache/ttl.py,sha256=_lWvNx1CTE4RcFEOUYkADd7_k4I13SLmtK0AMRUq2OM,1945
131
131
  svc_infra/cache/utils.py,sha256=-LWr5IiJCNm3pwaoeCVlxNknnO2ChNKFcAGlFU98kjg,4856
132
- svc_infra/cli/__init__.py,sha256=enGeMhxOjfeClic51C4QB2Car3DDZD3A9P9R_8YfYHQ,926
132
+ svc_infra/cli/__init__.py,sha256=3H3RePgCv_fCw9mFzYkbdn1VEeiZ1T88_BdloqrlEPY,1321
133
133
  svc_infra/cli/__main__.py,sha256=5BjNuyet8AY-POwoF5rGt722rHQ7tJ0Vf0UFUfzzi-I,58
134
134
  svc_infra/cli/cmds/__init__.py,sha256=xKVXpMP_fD7jfmYonxWxh5LKHUQiuIFaJgkpqtkPt-M,1051
135
135
  svc_infra/cli/cmds/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
136
  svc_infra/cli/cmds/db/nosql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
137
137
  svc_infra/cli/cmds/db/nosql/mongo/README.md,sha256=0u3XLeoBd0XQzXwwfEiFISMIij11TJ9iOGzrysBvsFk,1788
138
138
  svc_infra/cli/cmds/db/nosql/mongo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
- svc_infra/cli/cmds/db/nosql/mongo/mongo_cmds.py,sha256=83_I0-63aRyR2uRLhpG1DKavH8BJ6fwdL3qpCpksyBU,6109
140
- svc_infra/cli/cmds/db/nosql/mongo/mongo_scaffold_cmds.py,sha256=gsv7V3eGxyhQQm4J8IPYV9xQkdv0DoX7txcPLgbiejk,4277
139
+ svc_infra/cli/cmds/db/nosql/mongo/mongo_cmds.py,sha256=s5oAlZ9bYndiRhtmi9gSbcJPvR82bwCGRbxAF_ziBx4,6125
140
+ svc_infra/cli/cmds/db/nosql/mongo/mongo_scaffold_cmds.py,sha256=AR2sNt8Faxa6vAJ3MxGSWqLU54DMOL_r72hDtnEk4Pg,4253
141
141
  svc_infra/cli/cmds/db/sql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
142
- svc_infra/cli/cmds/db/sql/alembic_cmds.py,sha256=kkAu8sfBLWbb9ApMS95b7b_c6GifqvPaRsO7K8icMVI,9649
143
- svc_infra/cli/cmds/db/sql/sql_export_cmds.py,sha256=6MxoQO-9upoXg0cl1RHIqz96yXFVGidiBYp_ewhB0E0,2700
144
- svc_infra/cli/cmds/db/sql/sql_scaffold_cmds.py,sha256=eNTCqHXOxgl9H3WTbGVn9BHXYwCpjIEJsDqhEFdrYMM,4613
145
- svc_infra/cli/cmds/docs/docs_cmds.py,sha256=nvqxkqeYNSV79Eeq0Kv8PN1M8CbyS3lnrFNjHNlO53w,6661
142
+ svc_infra/cli/cmds/db/sql/alembic_cmds.py,sha256=uCreHg69Zf6B5gbv9Dm39jCRk6q2KQy_05A-75IP0Fg,9650
143
+ svc_infra/cli/cmds/db/sql/sql_export_cmds.py,sha256=YpkguUJFeFApMphVkhOJllTi25ejlsQaJarMe6vJD54,2685
144
+ svc_infra/cli/cmds/db/sql/sql_scaffold_cmds.py,sha256=MKc_T_tY1Y_wQl7XTlq8GhYWMMI1q1_vcFZVPOEcNUg,4601
145
+ svc_infra/cli/cmds/docs/docs_cmds.py,sha256=vRDhddel_X9MCfCVRvV7_Ns7sB3awfwSVWV0HqKLRKg,7653
146
146
  svc_infra/cli/cmds/dx/__init__.py,sha256=wQtl3-kOgoESlpVkjl3YFtqkOnQSIvVsOdutiaZFejM,197
147
147
  svc_infra/cli/cmds/dx/dx_cmds.py,sha256=XTKUJzS3UIYn6h3CHzDEWKYJaWn0TzGiUCq3OeW27E0,3326
148
148
  svc_infra/cli/cmds/help.py,sha256=wGfZFMYaR2ZPwW2JwKDU7M3m4AtdCd8GRQ412AmEBUM,758
149
149
  svc_infra/cli/cmds/jobs/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
150
150
  svc_infra/cli/cmds/jobs/jobs_cmds.py,sha256=l-w5GuR82GWR_F1CA7WPYAM895XBD8TQj_hZ6retBv0,1252
151
151
  svc_infra/cli/cmds/obs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
152
- svc_infra/cli/cmds/obs/obs_cmds.py,sha256=fltUZu5fcnZdl0_JPJBIxIaA1Xqpw1BXE-SWBP-PRuY,6485
152
+ svc_infra/cli/cmds/obs/obs_cmds.py,sha256=cAFzkO6j6FCZZxn5ch93Gq4TflV5Bx-6l3gyhKemxqM,6505
153
153
  svc_infra/cli/cmds/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
154
  svc_infra/cli/cmds/sdk/sdk_cmds.py,sha256=xzEbhA-L5bXMxf-DFzYXkdITfC4ua1Lt8I9x6PoEax0,2886
155
155
  svc_infra/cli/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -169,7 +169,7 @@ svc_infra/db/nosql/constants.py,sha256=Z9bJImxwb8D7vovASFegv8XMwaWcM28tsKJV2Sjyw
169
169
  svc_infra/db/nosql/core.py,sha256=hWda-OsiutD_7wVLI_S6QkkH6gHK8oHbVzRPjNfIBxY,4634
170
170
  svc_infra/db/nosql/indexes.py,sha256=XCVeSM73x3iF1bWITlyvYOr89dkcgliRcXUMTPg8Tmo,2302
171
171
  svc_infra/db/nosql/management.py,sha256=YreJXcNpPBAQTRGvyXjDK4pJhNL87hljT_2-i7CAlvg,3468
172
- svc_infra/db/nosql/mongo/README.md,sha256=Trygd6gkfMImErrBsR1_DMaxeeUGnmwOFL-9IYX316s,11681
172
+ svc_infra/db/nosql/mongo/README.md,sha256=rFGck7VMGOMh9PZ8KkgDbxzZfbsWAoTJg5UWGlvK4oM,11687
173
173
  svc_infra/db/nosql/mongo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
174
174
  svc_infra/db/nosql/mongo/client.py,sha256=dAhbi6cnhrTz6AgHW48hrXt-ptVl3X8_b75yAyjoOa0,1325
175
175
  svc_infra/db/nosql/mongo/settings.py,sha256=uat8k2FlgBmcEpcKXgzYvIK-_Zi4n-lnFEjlMqr23q8,522
@@ -228,7 +228,7 @@ svc_infra/jobs/redis_queue.py,sha256=wgmWKslF1dkYscJe49UgUX7gwEuGyOUWEb0-pn82I3g
228
228
  svc_infra/jobs/scheduler.py,sha256=dTUEEyEuTVHNmJT8wPdMu4YjnTN7R_YW67gtCKpqC7M,1180
229
229
  svc_infra/jobs/worker.py,sha256=T2A575_mnieJHPOYU_FseubLA_HQf9pB4CkRgzRJBHU,694
230
230
  svc_infra/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
231
- svc_infra/mcp/svc_infra_mcp.py,sha256=NmBY7AM3_pnHAumE-eM5Njr8kpb7Gh1-fjcZAEammiI,1927
231
+ svc_infra/mcp/svc_infra_mcp.py,sha256=x8wEB1YhnM2X3_3AUmKl6qKmQcL63dGbJ71WlzigHs8,2423
232
232
  svc_infra/obs/README.md,sha256=pmd6AyFZW3GCCi0sr3uTHrPj5KgAI8rrXw8QPkrf1R8,8021
233
233
  svc_infra/obs/__init__.py,sha256=t5DgkiuuhHnfAHChzYqCI1-Fpr68iQ0A1nHOLFIlAuM,75
234
234
  svc_infra/obs/add.py,sha256=Qa8pswZDxspIn3oniqe8NYeHmVhFwiYOYxF9xNAyCOs,4016
@@ -296,7 +296,7 @@ svc_infra/webhooks/fastapi.py,sha256=BCNvGNxukf6dC2a4i-6en-PrjBGV19YvCWOot5lXWsA
296
296
  svc_infra/webhooks/router.py,sha256=6JvAVPMEth_xxHX-IsIOcyMgHX7g1H0OVxVXKLuMp9w,1596
297
297
  svc_infra/webhooks/service.py,sha256=hWgiJRXKBwKunJOx91C7EcLUkotDtD3Xp0RT6vj2IC0,1797
298
298
  svc_infra/webhooks/signing.py,sha256=NCwdZzmravUe7HVIK_uXK0qqf12FG-_MVsgPvOw6lsM,784
299
- svc_infra-0.1.618.dist-info/METADATA,sha256=mH41WGLu0texy6G1rqK_cX5DmiJZFrhIN6kn6GgvLfE,8106
300
- svc_infra-0.1.618.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
301
- svc_infra-0.1.618.dist-info/entry_points.txt,sha256=6x_nZOsjvn6hRZsMgZLgTasaCSKCgAjsGhACe_CiP0U,48
302
- svc_infra-0.1.618.dist-info/RECORD,,
299
+ svc_infra-0.1.620.dist-info/METADATA,sha256=Ii8wzmysVqUARGfBUES-2TQIMzhyeAGvGimkSTMIpYg,8106
300
+ svc_infra-0.1.620.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
301
+ svc_infra-0.1.620.dist-info/entry_points.txt,sha256=6x_nZOsjvn6hRZsMgZLgTasaCSKCgAjsGhACe_CiP0U,48
302
+ svc_infra-0.1.620.dist-info/RECORD,,