Files
Vishesh 'ironeagle' Bangotra 24ecde4222
All checks were successful
continuous-integration/drone/push Build is passing
added more libs
2026-01-22 17:20:17 +05:30

2328 lines
52 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="prev" href="../auth/google/">
<link rel="next" href="store/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.23">
<title>Credentials - mail_intake</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.84d31ad4.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Inter:300,300i,400,400i,700,700i%7CJetBrains+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Inter";--md-code-font:"JetBrains Mono"}</style>
<link rel="stylesheet" href="../../assets/_mkdocstrings.css">
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#credentials" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="mail_intake" class="md-header__button md-logo" aria-label="mail_intake" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
mail_intake
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Credentials
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="deep-purple" data-md-color-accent="cyan" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../" class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../ingestion/" class="md-tabs__link">
Core API
</a>
</li>
<li class="md-tabs__item">
<a href="../models/" class="md-tabs__link">
Domain Models
</a>
</li>
<li class="md-tabs__item">
<a href="../adapters/" class="md-tabs__link">
Provider Adapters
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="../auth/" class="md-tabs__link">
Authentication & Storage
</a>
</li>
<li class="md-tabs__item">
<a href="../parsers/" class="md-tabs__link">
Normalization & Parsing
</a>
</li>
<li class="md-tabs__item">
<a href="../config/" class="md-tabs__link">
Configuration & Errors
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="mail_intake" class="md-nav__button md-logo" aria-label="mail_intake" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
mail_intake
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../" class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Core API
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Core API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../ingestion/" class="md-nav__link">
<span class="md-ellipsis">
Ingestion
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../ingestion/reader/" class="md-nav__link">
<span class="md-ellipsis">
Reader
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
Domain Models
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
Domain Models
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../models/" class="md-nav__link">
<span class="md-ellipsis">
Models
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../models/message/" class="md-nav__link">
<span class="md-ellipsis">
Message
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../models/thread/" class="md-nav__link">
<span class="md-ellipsis">
Thread
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-ellipsis">
Provider Adapters
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Provider Adapters
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../adapters/" class="md-nav__link">
<span class="md-ellipsis">
Adapters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adapters/base/" class="md-nav__link">
<span class="md-ellipsis">
Base
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../adapters/gmail/" class="md-nav__link">
<span class="md-ellipsis">
Gmail
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-ellipsis">
Authentication & Storage
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Authentication & Storage
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../auth/" class="md-nav__link">
<span class="md-ellipsis">
Auth
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../auth/base/" class="md-nav__link">
<span class="md-ellipsis">
Base
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../auth/google/" class="md-nav__link">
<span class="md-ellipsis">
Google
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Credentials
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Credentials
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#mail_intake.credentials" class="md-nav__link">
<span class="md-ellipsis">
credentials
</span>
</a>
<nav class="md-nav" aria-label="credentials">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore" class="md-nav__link">
<span class="md-ellipsis">
CredentialStore
</span>
</a>
<nav class="md-nav" aria-label="CredentialStore">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore.clear" class="md-nav__link">
<span class="md-ellipsis">
clear
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore.load" class="md-nav__link">
<span class="md-ellipsis">
load
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore.save" class="md-nav__link">
<span class="md-ellipsis">
save
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore" class="md-nav__link">
<span class="md-ellipsis">
PickleCredentialStore
</span>
</a>
<nav class="md-nav" aria-label="PickleCredentialStore">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore.clear" class="md-nav__link">
<span class="md-ellipsis">
clear
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore.load" class="md-nav__link">
<span class="md-ellipsis">
load
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore.save" class="md-nav__link">
<span class="md-ellipsis">
save
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore" class="md-nav__link">
<span class="md-ellipsis">
RedisCredentialStore
</span>
</a>
<nav class="md-nav" aria-label="RedisCredentialStore">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore.clear" class="md-nav__link">
<span class="md-ellipsis">
clear
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore.load" class="md-nav__link">
<span class="md-ellipsis">
load
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore.save" class="md-nav__link">
<span class="md-ellipsis">
save
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="store/" class="md-nav__link">
<span class="md-ellipsis">
Store
</span>
</a>
</li>
<li class="md-nav__item">
<a href="pickle/" class="md-nav__link">
<span class="md-ellipsis">
Pickle
</span>
</a>
</li>
<li class="md-nav__item">
<a href="redis/" class="md-nav__link">
<span class="md-ellipsis">
Redis
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
Normalization & Parsing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Normalization & Parsing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../parsers/" class="md-nav__link">
<span class="md-ellipsis">
Parsers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../parsers/body/" class="md-nav__link">
<span class="md-ellipsis">
Body
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../parsers/headers/" class="md-nav__link">
<span class="md-ellipsis">
Headers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../parsers/subject/" class="md-nav__link">
<span class="md-ellipsis">
Subject
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Configuration & Errors
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Configuration & Errors
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../config/" class="md-nav__link">
<span class="md-ellipsis">
Config
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../exceptions/" class="md-nav__link">
<span class="md-ellipsis">
Exceptions
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#mail_intake.credentials" class="md-nav__link">
<span class="md-ellipsis">
credentials
</span>
</a>
<nav class="md-nav" aria-label="credentials">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore" class="md-nav__link">
<span class="md-ellipsis">
CredentialStore
</span>
</a>
<nav class="md-nav" aria-label="CredentialStore">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore.clear" class="md-nav__link">
<span class="md-ellipsis">
clear
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore.load" class="md-nav__link">
<span class="md-ellipsis">
load
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.CredentialStore.save" class="md-nav__link">
<span class="md-ellipsis">
save
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore" class="md-nav__link">
<span class="md-ellipsis">
PickleCredentialStore
</span>
</a>
<nav class="md-nav" aria-label="PickleCredentialStore">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore.clear" class="md-nav__link">
<span class="md-ellipsis">
clear
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore.load" class="md-nav__link">
<span class="md-ellipsis">
load
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.PickleCredentialStore.save" class="md-nav__link">
<span class="md-ellipsis">
save
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore" class="md-nav__link">
<span class="md-ellipsis">
RedisCredentialStore
</span>
</a>
<nav class="md-nav" aria-label="RedisCredentialStore">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore.clear" class="md-nav__link">
<span class="md-ellipsis">
clear
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore.load" class="md-nav__link">
<span class="md-ellipsis">
load
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#mail_intake.credentials.RedisCredentialStore.save" class="md-nav__link">
<span class="md-ellipsis">
save
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="credentials">Credentials</h1>
<div class="doc doc-object doc-module">
<h2 id="mail_intake.credentials" class="doc doc-heading">
<span class="doc doc-object-name doc-module-name">mail_intake.credentials</span>
</h2>
<div class="doc doc-contents first">
<p>Credential persistence interfaces and implementations for Mail Intake.</p>
<p>This package defines the abstractions and concrete implementations used
to persist authentication credentials across Mail Intake components.</p>
<p>The credential persistence layer is intentionally decoupled from
authentication logic. Authentication providers are responsible for
credential acquisition, validation, and refresh, while implementations
within this package are responsible solely for storage and retrieval.</p>
<p>The package provides:
- A generic <code>CredentialStore</code> abstraction defining the persistence contract
- Local filesystembased storage for development and single-node use
- Distributed, Redis-backed storage for production and scaled deployments</p>
<p>Credential lifecycle management, interpretation, and security policy
decisions remain the responsibility of authentication providers.</p>
<div class="doc doc-children">
<div class="doc doc-object doc-class">
<h3 id="mail_intake.credentials.CredentialStore" class="doc doc-heading">
<span class="doc doc-object-name doc-class-name">CredentialStore</span>
</h3>
<div class="doc doc-contents ">
<p class="doc doc-class-bases">
Bases: <code><span title="abc.ABC">ABC</span></code>, <code><span title="typing.Generic">Generic</span>[<span title="mail_intake.credentials.store.T">T</span>]</code></p>
<p>Abstract base class defining a generic persistence interface for
authentication credentials.</p>
<p>This interface separates <em>credential lifecycle management</em> from
<em>credential storage mechanics</em>. Implementations are responsible
only for persistence concerns, while authentication providers
retain full control over credential creation, validation, refresh,
and revocation logic.</p>
<p>The store is intentionally agnostic to:
- The concrete credential type being stored
- The serialization format used to persist credentials
- The underlying storage backend or durability guarantees</p>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.CredentialStore.clear" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">clear</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-abstractmethod"><code>abstractmethod</code></small>
</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">clear</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kc">None</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Remove any persisted credentials from the store.</p>
<p>This method is called when credentials are known to be invalid,
revoked, corrupted, or otherwise unusable, and must ensure that
no stale authentication material remains accessible.</p>
<p>Implementations should treat this operation as idempotent.</p>
</div>
</div>
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.CredentialStore.load" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">load</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-abstractmethod"><code>abstractmethod</code></small>
</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">load</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="n">T</span><span class="p">]</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Load previously persisted credentials.</p>
<p>Implementations should return <code>None</code> when no credentials are
present or when stored credentials cannot be successfully
decoded or deserialized.</p>
<p>The store must not attempt to validate, refresh, or otherwise
interpret the returned credentials.</p>
<p><span class="doc-section-title">Returns:</span></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code><span title="typing.Optional">Optional</span>[<span title="mail_intake.credentials.store.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>An instance of type <code>T</code> if credentials are available and</p>
</div>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code><span title="typing.Optional">Optional</span>[<span title="mail_intake.credentials.store.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>loadable; otherwise <code>None</code>.</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.CredentialStore.save" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">save</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-abstractmethod"><code>abstractmethod</code></small>
</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">save</span><span class="p">(</span><span class="n">credentials</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Persist credentials to the underlying storage backend.</p>
<p>This method is invoked when credentials are newly obtained or
have been refreshed and are known to be valid at the time of
persistence.</p>
<p>Implementations are responsible for:
- Ensuring durability appropriate to the deployment context
- Applying encryption or access controls where required
- Overwriting any previously stored credentials</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td><code>credentials</code></td>
<td>
<code><span title="mail_intake.credentials.store.T">T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The credential object to persist.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h3 id="mail_intake.credentials.PickleCredentialStore" class="doc doc-heading">
<span class="doc doc-object-name doc-class-name">PickleCredentialStore</span>
</h3>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">PickleCredentialStore</span><span class="p">(</span><span class="n">path</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span>
</code></pre></div>
<div class="doc doc-contents ">
<p class="doc doc-class-bases">
Bases: <code><a class="autorefs autorefs-internal" title="mail_intake.credentials.store.CredentialStore" href="store/#mail_intake.credentials.store.CredentialStore">CredentialStore</a>[<span title="mail_intake.credentials.pickle.T">T</span>]</code></p>
<p>Filesystem-backed credential store using pickle serialization.</p>
<p>This store persists credentials as a pickled object on the local
filesystem. It is a simple implementation intended primarily for
development, testing, and single-process execution contexts.</p>
<p>This implementation:
- Stores credentials on the local filesystem
- Uses pickle for serialization and deserialization
- Does not provide encryption, locking, or concurrency guarantees</p>
<p>Credential lifecycle management, validation, and refresh logic are
explicitly out of scope for this class.</p>
<p>Initialize a pickle-backed credential store.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td><code>path</code></td>
<td>
<code>str</code>
</td>
<td>
<div class="doc-md-description">
<p>Filesystem path where credentials will be stored.
The file will be created or overwritten as needed.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.PickleCredentialStore.clear" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">clear</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">clear</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kc">None</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Remove persisted credentials from the local filesystem.</p>
<p>This method deletes the credential file if it exists and should
be treated as an idempotent operation.</p>
</div>
</div>
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.PickleCredentialStore.load" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">load</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">load</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="n">T</span><span class="p">]</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Load credentials from the local filesystem.</p>
<p>If the credential file does not exist or cannot be successfully
deserialized, this method returns <code>None</code>.</p>
<p>The store does not attempt to validate or interpret the returned
credentials.</p>
<p><span class="doc-section-title">Returns:</span></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code><span title="typing.Optional">Optional</span>[<span title="mail_intake.credentials.pickle.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>An instance of type <code>T</code> if credentials are present and</p>
</div>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code><span title="typing.Optional">Optional</span>[<span title="mail_intake.credentials.pickle.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>successfully deserialized; otherwise <code>None</code>.</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.PickleCredentialStore.save" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">save</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">save</span><span class="p">(</span><span class="n">credentials</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Persist credentials to the local filesystem.</p>
<p>Any previously stored credentials at the configured path are
overwritten.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td><code>credentials</code></td>
<td>
<code><span title="mail_intake.credentials.pickle.T">T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The credential object to persist.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h3 id="mail_intake.credentials.RedisCredentialStore" class="doc doc-heading">
<span class="doc doc-object-name doc-class-name">RedisCredentialStore</span>
</h3>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">RedisCredentialStore</span><span class="p">(</span><span class="n">redis_client</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">key</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">serialize</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="n">T</span><span class="p">],</span> <span class="nb">bytes</span><span class="p">],</span> <span class="n">deserialize</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[</span><span class="nb">bytes</span><span class="p">],</span> <span class="n">T</span><span class="p">],</span> <span class="n">ttl_seconds</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span>
</code></pre></div>
<div class="doc doc-contents ">
<p class="doc doc-class-bases">
Bases: <code><a class="autorefs autorefs-internal" title="mail_intake.credentials.store.CredentialStore" href="store/#mail_intake.credentials.store.CredentialStore">CredentialStore</a>[<span title="mail_intake.credentials.redis.T">T</span>]</code></p>
<p>Redis-backed implementation of <code>CredentialStore</code>.</p>
<p>This store persists credentials in Redis and is suitable for
distributed and horizontally scaled deployments where credentials
must be shared across multiple processes or nodes.</p>
<p>The store is intentionally generic and delegates all serialization
concerns to caller-provided functions. This avoids unsafe mechanisms
such as pickle and allows credential formats to be explicitly
controlled and audited.</p>
<p>This class is responsible only for persistence and retrieval.
It does not interpret, validate, refresh, or otherwise manage
the lifecycle of the credentials being stored.</p>
<p>Initialize a Redis-backed credential store.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td><code>redis_client</code></td>
<td>
<code><span title="typing.Any">Any</span></code>
</td>
<td>
<div class="doc-md-description">
<p>An initialized Redis client instance (for example,
<code>redis.Redis</code> or a compatible interface) used to
communicate with the Redis server.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td><code>key</code></td>
<td>
<code>str</code>
</td>
<td>
<div class="doc-md-description">
<p>The Redis key under which credentials are stored.
Callers are responsible for applying appropriate
namespacing to avoid collisions.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td><code>serialize</code></td>
<td>
<code><span title="typing.Callable">Callable</span>[[<span title="mail_intake.credentials.redis.T">T</span>], bytes]</code>
</td>
<td>
<div class="doc-md-description">
<p>A callable that converts a credential object of type
<code>T</code> into a <code>bytes</code> representation suitable for
storage in Redis.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td><code>deserialize</code></td>
<td>
<code><span title="typing.Callable">Callable</span>[[bytes], <span title="mail_intake.credentials.redis.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>A callable that converts a <code>bytes</code> payload retrieved
from Redis back into a credential object of type <code>T</code>.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td><code>ttl_seconds</code></td>
<td>
<code><span title="typing.Optional">Optional</span>[int]</code>
</td>
<td>
<div class="doc-md-description">
<p>Optional time-to-live (TTL) for the stored credentials,
expressed in seconds. When provided, Redis will
automatically expire the stored credentials after the
specified duration. If <code>None</code>, credentials are stored
without an expiration.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.RedisCredentialStore.clear" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">clear</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">clear</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="kc">None</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Remove stored credentials from Redis.</p>
<p>This operation deletes the configured Redis key if it exists.
Implementations should treat this method as idempotent.</p>
</div>
</div>
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.RedisCredentialStore.load" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">load</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">load</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="n">T</span><span class="p">]</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Load credentials from Redis.</p>
<p>If no value exists for the configured key, or if the stored
payload cannot be successfully deserialized, this method
returns <code>None</code>.</p>
<p>The store does not attempt to validate the returned credentials
or determine whether they are expired or otherwise usable.</p>
<p><span class="doc-section-title">Returns:</span></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code><span title="typing.Optional">Optional</span>[<span title="mail_intake.credentials.redis.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>An instance of type <code>T</code> if credentials are present and</p>
</div>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code><span title="typing.Optional">Optional</span>[<span title="mail_intake.credentials.redis.T">T</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>successfully deserialized; otherwise <code>None</code>.</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="doc doc-object doc-function">
<h4 id="mail_intake.credentials.RedisCredentialStore.save" class="doc doc-heading">
<span class="doc doc-object-name doc-function-name">save</span>
</h4>
<div class="doc-signature highlight"><pre><span></span><code><span class="nf">save</span><span class="p">(</span><span class="n">credentials</span><span class="p">:</span> <span class="n">T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span>
</code></pre></div>
<div class="doc doc-contents ">
<p>Persist credentials to Redis.</p>
<p>Any previously stored credentials under the same key are
overwritten. If a TTL is configured, the credentials will
expire automatically after the specified duration.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td><code>credentials</code></td>
<td>
<code><span title="mail_intake.credentials.redis.T">T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The credential object to persist.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../..", "features": ["navigation.tabs", "navigation.expand", "navigation.top", "navigation.instant", "content.code.copy", "content.code.annotate"], "search": "../../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>