feat(vault): add VAULT_TAG to share key vault across services

Lets sibling services read/write one key-vault namespace instead of being tied to their own tag. New Service.VAULT_TAG class var, resolved via Services.get_vault_tag() in both the dl and serve paths. AMZN_WEB opts into the AMZN namespace; EXAMPLE documents usage.
This commit is contained in:
imSp4rky
2026-06-07 15:59:59 -06:00
parent 4a543c59e6
commit ce0d9d8355
5 changed files with 24 additions and 3 deletions

View File

@@ -618,6 +618,7 @@ class dl:
)
self.service = Services.get_tag(ctx.invoked_subcommand)
self.vault_service = Services.get_vault_tag(self.service)
service_dl_config = config.services.get(self.service, {}).get("dl", {})
if service_dl_config:
param_types = {param.name: param.type for param in ctx.command.params if param.name}
@@ -818,7 +819,7 @@ class dl:
cdm_only = ctx.params.get("cdm_only")
if cdm_only:
self.vaults = Vaults(self.service)
self.vaults = Vaults(self.vault_service)
self.log.info("CDM-only mode: Skipping vault loading")
if self.debug_logger:
self.debug_logger.log(
@@ -829,7 +830,7 @@ class dl:
)
else:
with console.status("Loading Key Vaults...", spinner="dots"):
self.vaults = Vaults(self.service)
self.vaults = Vaults(self.vault_service)
total_vaults = len(config.key_vaults)
failed_vaults = []

View File

@@ -2009,9 +2009,10 @@ def _resolve_device_name(user_config: dict, drm_type: str, service_tag: str = ""
def _load_server_vaults(service_name: str) -> Any:
"""Load server vaults from config.key_vaults."""
from unshackle.core.config import config as app_config
from unshackle.core.services import Services
from unshackle.core.vaults import Vaults
vaults = Vaults(service_name)
vaults = Vaults(Services.get_vault_tag(service_name))
for vault_config in app_config.key_vaults:
cfg = vault_config.copy()
vault_type = cfg.pop("type", None)

View File

@@ -93,6 +93,8 @@ class Service(metaclass=ABCMeta):
# Abstract class variables
ALIASES: tuple[str, ...] = () # list of aliases for the service; alternatives to the service tag.
GEOFENCE: tuple[str, ...] = () # list of ip regions required to use the service. empty list == no specific region.
# vault namespace override; when set, key vault read/write uses this tag instead of the service's own.
VAULT_TAG: Optional[str] = None
def __init__(self, ctx: click.Context):
console.print(Padding(Rule(f"[rule.text]Service: {self.__class__.__name__}"), (1, 2)))

View File

@@ -274,5 +274,19 @@ class Services(click.Group):
raise KeyError(f"There is no Service added by the Tag '{tag}'")
@staticmethod
def get_vault_tag(name: str) -> str:
"""Resolve the key-vault namespace tag for a service.
Returns the service's VAULT_TAG override when set, otherwise its own tag.
Falls back to the resolved tag for non-local services (remote/import).
"""
tag = Services.get_tag(name)
try:
service = Services.load(tag)
except KeyError:
return tag
return getattr(service, "VAULT_TAG", None) or tag
__all__ = ("Services",)

View File

@@ -75,6 +75,9 @@ class EXAMPLE(Service):
TITLE_RE = r"^(?:https?://(?:www\.)?domain\.com/details/)?(?P<title_id>[^/?#]+)"
# NO_SUBTITLES: service-level idiom telling the pipeline subs are handled in-band.
NO_SUBTITLES = False
# VAULT_TAG: store/read keys under a different vault namespace than this service's tag.
# Lets sibling services share one key vault. Omit to use the service's own tag.
VAULT_TAG = "DIFFERENT_NAME"
# Map our API's range strings <-> unshackle's Video.Range enum.
VIDEO_RANGE_MAP = {