tba-app-backend-core 0.4.0.dev2__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.
- tba_app_backend_core-0.4.0.dev2/PKG-INFO +60 -0
- tba_app_backend_core-0.4.0.dev2/README.md +12 -0
- tba_app_backend_core-0.4.0.dev2/pyproject.toml +52 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/__init__.py +15 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/app.py +146 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/plugin.py +36 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/product.py +55 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/py.typed +0 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/__init__.py +3 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/admin_routes.py +353 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/advanced_protocols.py +170 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/auth_flows.py +16 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/authorization_server_metadata_surface.py +37 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/authorization_surface.py +15 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/authz_surface.py +14 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/client_registration_surface.py +366 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/device_authorization_surface.py +44 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/introspection_surface.py +247 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/login_surface.py +25 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/logout_surface.py +38 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/oidc_discovery_surface.py +79 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/par_surface.py +394 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/protected_resource_metadata_surface.py +34 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/resource_validation_metadata_surface.py +33 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/revocation_surface.py +39 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/standards_manifest.py +24 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/surface_api.py +284 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/token_exchange_surface.py +34 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/token_surface.py +12 -0
- tba_app_backend_core-0.4.0.dev2/src/tba_app_backend_core/surfaces/userinfo_surface.py +34 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tba-app-backend-core
|
|
3
|
+
Version: 0.4.0.dev2
|
|
4
|
+
Summary: Shared layer-90 ASGI and router composition for TBA backend applications.
|
|
5
|
+
License-Expression: Apache-2.0
|
|
6
|
+
Requires-Python: >=3.10,<3.15
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
13
|
+
Requires-Dist: tba-capability-client-secret-authentication (==0.4.0.dev2)
|
|
14
|
+
Requires-Dist: tba-contracts-identity (==0.4.0.dev2)
|
|
15
|
+
Requires-Dist: tba-operator-identity (==0.4.0.dev2)
|
|
16
|
+
Requires-Dist: tba-plugin-tigrbl (==0.4.0.dev2)
|
|
17
|
+
Requires-Dist: tba-primitives-identity (==0.4.0.dev2)
|
|
18
|
+
Requires-Dist: tba-protocol-gnap (==0.4.0.dev2)
|
|
19
|
+
Requires-Dist: tba-protocol-oauth (==0.4.0.dev2)
|
|
20
|
+
Requires-Dist: tba-provider-secret-hashing-bcrypt (==0.1.0)
|
|
21
|
+
Requires-Dist: tba-router-administration-gate (==0.4.0.dev2)
|
|
22
|
+
Requires-Dist: tba-router-oauth-authorization (==0.4.0.dev2)
|
|
23
|
+
Requires-Dist: tba-router-oauth-authorization-server-metadata (==0.4.0.dev2)
|
|
24
|
+
Requires-Dist: tba-router-oauth-device-authorization (==0.4.0.dev2)
|
|
25
|
+
Requires-Dist: tba-router-oauth-introspection (==0.4.0.dev2)
|
|
26
|
+
Requires-Dist: tba-router-oauth-protected-resource-metadata (==0.4.0.dev2)
|
|
27
|
+
Requires-Dist: tba-router-oauth-pushed-authorization-request (==0.4.0.dev2)
|
|
28
|
+
Requires-Dist: tba-router-oauth-registration (==0.4.0.dev2)
|
|
29
|
+
Requires-Dist: tba-router-oauth-revocation (==0.4.0.dev2)
|
|
30
|
+
Requires-Dist: tba-router-oauth-token (==0.4.0.dev2)
|
|
31
|
+
Requires-Dist: tba-router-oauth-token-exchange (==0.4.0.dev2)
|
|
32
|
+
Requires-Dist: tba-router-oidc-discovery (==0.4.0.dev2)
|
|
33
|
+
Requires-Dist: tba-router-oidc-logout (==0.4.0.dev2)
|
|
34
|
+
Requires-Dist: tba-router-oidc-userinfo (==0.4.0.dev2)
|
|
35
|
+
Requires-Dist: tba-router-resource-validation-metadata (==0.4.0.dev2)
|
|
36
|
+
Requires-Dist: tba-router-session-login (==0.4.0.dev2)
|
|
37
|
+
Requires-Dist: tba-runtime-identity (==0.4.0.dev2)
|
|
38
|
+
Requires-Dist: tba-runtime-identity-storage (==0.4.0.dev2)
|
|
39
|
+
Requires-Dist: tba-server-identity (==0.4.0.dev2)
|
|
40
|
+
Requires-Dist: tba-storage-core (==0.4.0.dev4)
|
|
41
|
+
Requires-Dist: tba-storage-oauth (==0.4.0.dev2)
|
|
42
|
+
Requires-Dist: tba-storage-tenancy (==0.4.0.dev2)
|
|
43
|
+
Requires-Dist: tigrbl (==0.4.5.dev8)
|
|
44
|
+
Project-URL: Homepage, https://github.com/tigrbl/tigrbl_auth
|
|
45
|
+
Project-URL: Repository, https://github.com/tigrbl/tigrbl_auth
|
|
46
|
+
Project-URL: Source, https://github.com/tigrbl/tigrbl_auth/tree/master/pkgs/90-backend-apps/tba-app-backend-core
|
|
47
|
+
Description-Content-Type: text/markdown
|
|
48
|
+
|
|
49
|
+
# tba-app-backend-core
|
|
50
|
+
|
|
51
|
+
Shared layer-90 composition for deployable TBA backend applications.
|
|
52
|
+
|
|
53
|
+
This package owns ASGI application construction, layer-80 router closure, HTTP
|
|
54
|
+
surface assembly, administrative gate wrapping, and product-surface selection.
|
|
55
|
+
Product backend-app packages supply a declared product contract and call the
|
|
56
|
+
shared build_product_app factory.
|
|
57
|
+
|
|
58
|
+
It does not own protocol semantics, capability implementations, durable table
|
|
59
|
+
behavior, runtime handlers, or storage. Those remain in layers 50, 40, 30, and
|
|
60
|
+
60 and are injected or imported downward.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# tba-app-backend-core
|
|
2
|
+
|
|
3
|
+
Shared layer-90 composition for deployable TBA backend applications.
|
|
4
|
+
|
|
5
|
+
This package owns ASGI application construction, layer-80 router closure, HTTP
|
|
6
|
+
surface assembly, administrative gate wrapping, and product-surface selection.
|
|
7
|
+
Product backend-app packages supply a declared product contract and call the
|
|
8
|
+
shared build_product_app factory.
|
|
9
|
+
|
|
10
|
+
It does not own protocol semantics, capability implementations, durable table
|
|
11
|
+
behavior, runtime handlers, or storage. Those remain in layers 50, 40, 30, and
|
|
12
|
+
60 and are injected or imported downward.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tba-app-backend-core"
|
|
3
|
+
version = "0.4.0.dev2"
|
|
4
|
+
description = "Shared layer-90 ASGI and router composition for TBA backend applications."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10,<3.15"
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"tigrbl==0.4.5.dev8",
|
|
10
|
+
"tba-protocol-gnap==0.4.0.dev2",
|
|
11
|
+
"tba-protocol-oauth==0.4.0.dev2",
|
|
12
|
+
"tba-plugin-tigrbl==0.4.0.dev2",
|
|
13
|
+
"tba-router-administration-gate==0.4.0.dev2",
|
|
14
|
+
"tba-router-oauth-authorization==0.4.0.dev2",
|
|
15
|
+
"tba-router-oauth-authorization-server-metadata==0.4.0.dev2",
|
|
16
|
+
"tba-router-oauth-device-authorization==0.4.0.dev2",
|
|
17
|
+
"tba-router-oauth-introspection==0.4.0.dev2",
|
|
18
|
+
"tba-router-oauth-pushed-authorization-request==0.4.0.dev2",
|
|
19
|
+
"tba-router-oauth-protected-resource-metadata==0.4.0.dev2",
|
|
20
|
+
"tba-router-oauth-registration==0.4.0.dev2",
|
|
21
|
+
"tba-router-oauth-revocation==0.4.0.dev2",
|
|
22
|
+
"tba-router-oauth-token==0.4.0.dev2",
|
|
23
|
+
"tba-router-oauth-token-exchange==0.4.0.dev2",
|
|
24
|
+
"tba-router-oidc-discovery==0.4.0.dev2",
|
|
25
|
+
"tba-router-oidc-logout==0.4.0.dev2",
|
|
26
|
+
"tba-router-oidc-userinfo==0.4.0.dev2",
|
|
27
|
+
"tba-router-resource-validation-metadata==0.4.0.dev2",
|
|
28
|
+
"tba-router-session-login==0.4.0.dev2",
|
|
29
|
+
"tba-capability-client-secret-authentication==0.4.0.dev2",
|
|
30
|
+
"tba-contracts-identity==0.4.0.dev2",
|
|
31
|
+
"tba-primitives-identity==0.4.0.dev2",
|
|
32
|
+
"tba-operator-identity==0.4.0.dev2",
|
|
33
|
+
"tba-runtime-identity==0.4.0.dev2",
|
|
34
|
+
"tba-server-identity==0.4.0.dev2",
|
|
35
|
+
"tba-storage-core==0.4.0.dev4",
|
|
36
|
+
"tba-storage-oauth==0.4.0.dev2",
|
|
37
|
+
"tba-storage-tenancy==0.4.0.dev2",
|
|
38
|
+
"tba-runtime-identity-storage==0.4.0.dev2",
|
|
39
|
+
"tba-provider-secret-hashing-bcrypt==0.1.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://github.com/tigrbl/tigrbl_auth"
|
|
44
|
+
Repository = "https://github.com/tigrbl/tigrbl_auth"
|
|
45
|
+
Source = "https://github.com/tigrbl/tigrbl_auth/tree/master/pkgs/90-backend-apps/tba-app-backend-core"
|
|
46
|
+
|
|
47
|
+
[build-system]
|
|
48
|
+
requires = ["poetry-core>=1.0.0"]
|
|
49
|
+
build-backend = "poetry.core.masonry.api"
|
|
50
|
+
|
|
51
|
+
[tool.poetry]
|
|
52
|
+
packages = [{ include = "tba_app_backend_core", from = "src" }]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Shared backend-application composition APIs."""
|
|
2
|
+
|
|
3
|
+
from .app import app, build_app, build_application_runtime_plan
|
|
4
|
+
from .plugin import TbaBackendAppPlugin, install
|
|
5
|
+
from .product import build_product_app, validate_backend_app_contract
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"app",
|
|
9
|
+
"build_app",
|
|
10
|
+
"build_application_runtime_plan",
|
|
11
|
+
"TbaBackendAppPlugin",
|
|
12
|
+
"build_product_app",
|
|
13
|
+
"install",
|
|
14
|
+
"validate_backend_app_contract",
|
|
15
|
+
]
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import replace
|
|
4
|
+
from importlib.metadata import (
|
|
5
|
+
PackageNotFoundError,
|
|
6
|
+
version as installed_package_version,
|
|
7
|
+
)
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from tba_runtime_identity.deployment import ResolvedDeployment, resolve_deployment
|
|
12
|
+
from tba_operator_identity.repo_truth import (
|
|
13
|
+
package_version as repository_package_version,
|
|
14
|
+
)
|
|
15
|
+
from tba_runtime_identity import LazyASGIApplication
|
|
16
|
+
from tba_server_identity.composition.app import (
|
|
17
|
+
_load_default_settings,
|
|
18
|
+
build_application_runtime_plan as _build_application_runtime_plan,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from tigrbl import TigrblApp
|
|
23
|
+
from tba_server_identity.composition.lifecycle import AssemblyFactory
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _runtime_package_version() -> str:
|
|
27
|
+
try:
|
|
28
|
+
return installed_package_version("tba-app-backend-core")
|
|
29
|
+
except PackageNotFoundError:
|
|
30
|
+
return repository_package_version(Path(__file__).resolve().parents[2])
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _path_has_prefix(path: str, prefix: str) -> bool:
|
|
34
|
+
return path == prefix or path.startswith(f"{prefix}/")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _hide_disabled_control_plane_docs(
|
|
38
|
+
app: object,
|
|
39
|
+
deployment: ResolvedDeployment,
|
|
40
|
+
*,
|
|
41
|
+
diagnostics_prefix: str,
|
|
42
|
+
) -> None:
|
|
43
|
+
routes = getattr(app, "_routes", None)
|
|
44
|
+
if not isinstance(routes, list):
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
hidden = []
|
|
48
|
+
for route in routes:
|
|
49
|
+
path = str(getattr(route, "path_template", None) or getattr(route, "path", ""))
|
|
50
|
+
hide = not deployment.flag_enabled(
|
|
51
|
+
"surface_diagnostics_enabled"
|
|
52
|
+
) and _path_has_prefix(path, diagnostics_prefix)
|
|
53
|
+
if hide and hasattr(route, "include_in_schema"):
|
|
54
|
+
hidden.append(replace(route, include_in_schema=False))
|
|
55
|
+
else:
|
|
56
|
+
hidden.append(route)
|
|
57
|
+
routes[:] = hidden
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def build_app(
|
|
61
|
+
settings_obj: object | None = None,
|
|
62
|
+
*,
|
|
63
|
+
deployment: ResolvedDeployment | None = None,
|
|
64
|
+
runtime_assembly_factory: AssemblyFactory | None = None,
|
|
65
|
+
) -> "TigrblApp":
|
|
66
|
+
resolved_settings = (
|
|
67
|
+
settings_obj if settings_obj is not None else _load_default_settings()
|
|
68
|
+
)
|
|
69
|
+
resolved_deployment = deployment or resolve_deployment(resolved_settings)
|
|
70
|
+
if runtime_assembly_factory is None:
|
|
71
|
+
from tba_server_identity.composition.runtime_assembly import (
|
|
72
|
+
build_server_runtime_assembly_async,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
async def default_runtime_assembly_factory():
|
|
76
|
+
return await build_server_runtime_assembly_async(resolved_settings)
|
|
77
|
+
|
|
78
|
+
runtime_assembly_factory = default_runtime_assembly_factory
|
|
79
|
+
|
|
80
|
+
from tba_contracts_identity.protocol_configuration import (
|
|
81
|
+
ProtocolSettingsOverlay,
|
|
82
|
+
bind_protocol_settings,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
protocol_settings = ProtocolSettingsOverlay(
|
|
86
|
+
resolved_settings, _load_default_settings()
|
|
87
|
+
)
|
|
88
|
+
bind_protocol_settings(protocol_settings)
|
|
89
|
+
|
|
90
|
+
from tigrbl import TigrblApp
|
|
91
|
+
|
|
92
|
+
from tba_server_identity.composition.lifecycle import register_lifecycle
|
|
93
|
+
from tba_app_backend_core.surfaces import (
|
|
94
|
+
admin_resource_path_prefixes,
|
|
95
|
+
attach_runtime_surfaces,
|
|
96
|
+
)
|
|
97
|
+
from tba_router_administration_gate import AdminGate
|
|
98
|
+
from tba_runtime_identity_storage.engine import dsn
|
|
99
|
+
|
|
100
|
+
app = TigrblApp(
|
|
101
|
+
title="tba_auth",
|
|
102
|
+
version=_runtime_package_version(),
|
|
103
|
+
openapi_url="/openapi.json",
|
|
104
|
+
docs_url="/docs",
|
|
105
|
+
engine=dsn,
|
|
106
|
+
)
|
|
107
|
+
state = getattr(app, "state", None)
|
|
108
|
+
if state is not None:
|
|
109
|
+
state.tba_auth_deployment = resolved_deployment
|
|
110
|
+
state.tba_auth_settings = resolved_settings
|
|
111
|
+
surface_router = attach_runtime_surfaces(
|
|
112
|
+
app,
|
|
113
|
+
resolved_settings,
|
|
114
|
+
deployment=resolved_deployment,
|
|
115
|
+
diagnostics_prefix="/system",
|
|
116
|
+
)
|
|
117
|
+
_hide_disabled_control_plane_docs(
|
|
118
|
+
app,
|
|
119
|
+
resolved_deployment,
|
|
120
|
+
diagnostics_prefix="/system",
|
|
121
|
+
)
|
|
122
|
+
register_lifecycle(
|
|
123
|
+
app,
|
|
124
|
+
assembly_factory=runtime_assembly_factory,
|
|
125
|
+
surface_initializer=surface_router.initialize,
|
|
126
|
+
)
|
|
127
|
+
return AdminGate(
|
|
128
|
+
app,
|
|
129
|
+
deployment=resolved_deployment,
|
|
130
|
+
settings_obj=resolved_settings,
|
|
131
|
+
admin_path_prefixes=admin_resource_path_prefixes(resolved_deployment),
|
|
132
|
+
diagnostics_prefix="/system",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def build_application_runtime_plan(*args: object, **kwargs: object):
|
|
137
|
+
kwargs.setdefault(
|
|
138
|
+
"app_factory",
|
|
139
|
+
"tba_app_backend_core.app.build_app",
|
|
140
|
+
)
|
|
141
|
+
return _build_application_runtime_plan(*args, **kwargs)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
app = LazyASGIApplication(build_app)
|
|
145
|
+
|
|
146
|
+
__all__ = ["app", "build_app", "build_application_runtime_plan"]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Layer-90 host-application plugin with HTTP surface ownership."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from tba_plugin_tigrbl import TbaPlugin as RuntimePlugin
|
|
8
|
+
|
|
9
|
+
from .surfaces import attach_runtime_surfaces
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from tigrbl import TigrblApp
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TbaBackendAppPlugin(RuntimePlugin):
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
*,
|
|
19
|
+
diagnostics_prefix: str = "/system",
|
|
20
|
+
settings: object | None = None,
|
|
21
|
+
) -> None:
|
|
22
|
+
super().__init__(
|
|
23
|
+
surface_attacher=attach_runtime_surfaces,
|
|
24
|
+
diagnostics_prefix=diagnostics_prefix,
|
|
25
|
+
settings=settings,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def install(app: "TigrblApp", settings: object | None = None) -> "TigrblApp":
|
|
30
|
+
return TbaBackendAppPlugin(settings=settings).install(
|
|
31
|
+
app,
|
|
32
|
+
settings=settings,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__all__ = ["TbaBackendAppPlugin", "install"]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Product-specific backend application assembly."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from tba_runtime_identity.deployment import (
|
|
8
|
+
PRODUCT_SURFACE_REGISTRY,
|
|
9
|
+
resolve_deployment,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
from .app import build_app
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from tigrbl import TigrblApp
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def validate_backend_app_contract(contract: object, deployment: object) -> None:
|
|
19
|
+
expected_surface = getattr(contract, "product_surface", None)
|
|
20
|
+
actual_surface = getattr(deployment, "product_surface", None)
|
|
21
|
+
if expected_surface != actual_surface:
|
|
22
|
+
raise ValueError(
|
|
23
|
+
"backend-app contract product surface does not match deployment: "
|
|
24
|
+
f"{expected_surface!r} != {actual_surface!r}"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
declared_routers = tuple(getattr(contract, "mounted_router_packages", ()))
|
|
28
|
+
resolved_routers = tuple(getattr(deployment, "router_packages", ()))
|
|
29
|
+
if declared_routers != resolved_routers:
|
|
30
|
+
raise ValueError(
|
|
31
|
+
"backend-app contract router closure does not match deployment: "
|
|
32
|
+
f"{declared_routers!r} != {resolved_routers!r}"
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def build_product_app(
|
|
37
|
+
product_surface: str,
|
|
38
|
+
settings_obj: object | None = None,
|
|
39
|
+
*,
|
|
40
|
+
contract: object | None = None,
|
|
41
|
+
) -> "TigrblApp":
|
|
42
|
+
"""Build the shared ASGI app constrained to one declared product surface."""
|
|
43
|
+
if product_surface not in PRODUCT_SURFACE_REGISTRY:
|
|
44
|
+
raise ValueError(f"unknown tba_auth product surface: {product_surface}")
|
|
45
|
+
deployment = resolve_deployment(
|
|
46
|
+
settings_obj,
|
|
47
|
+
product_surface=product_surface,
|
|
48
|
+
runtime_style="standalone",
|
|
49
|
+
)
|
|
50
|
+
if contract is not None:
|
|
51
|
+
validate_backend_app_contract(contract, deployment)
|
|
52
|
+
return build_app(settings_obj, deployment=deployment)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
__all__ = ["build_product_app", "validate_backend_app_contract"]
|
|
File without changes
|