Metadata-Version: 2.5
Name: lupaxa-token-manager
Version: 0.1.0
Summary: Store API tokens in named profiles, with optional encryption, and emit them as shell exports.
Project-URL: Homepage, https://token-manager.thelupaxaproject.org/
Project-URL: Documentation, https://token-manager.thelupaxaproject.org/
Project-URL: Repository, https://github.com/lupaxa-developers-toolbox/token-manager
Project-URL: Issues, https://github.com/lupaxa-developers-toolbox/token-manager/issues
Author: The Lupaxa Project
License: MIT License
        
        Copyright (c) The Lupaxa Project
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENCE
Keywords: cli,credentials,encryption,profiles,tokens
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: bump-my-version>=1.2.0; extra == 'dev'
Requires-Dist: hatch>=1.12.0; extra == 'dev'
Requires-Dist: mkdocs-material==9.7.7; extra == 'dev'
Requires-Dist: mkdocs==1.6.1; extra == 'dev'
Requires-Dist: mypy>=1.12.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6.0; extra == 'dev'
Provides-Extra: test
Requires-Dist: pytest-cov>=5.0; extra == 'test'
Requires-Dist: pytest>=8.0; extra == 'test'
Description-Content-Type: text/markdown

<p align="center">
  <a href="https://github.com/lupaxa-developers-toolbox">
    <img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/organisations/developers-toolbox/readme-logo.png" alt="Developers Toolbox" />
  </a>
</p>

<h1 align="center">Token Manager</h1>

Store API tokens in named profiles and print them as shell exports.
Each profile can keep tokens as plaintext JSON, or encrypt them with
`gpg` or `openssl`.

The PyPI name is `lupaxa-token-manager`. The import path is
`lupaxa.token_manager`. The console scripts are `tokenctl` and
`token-manager`.

## Install

```bash
pip install lupaxa-token-manager
```

Requires Python 3.10 or newer. Encryption modes need the `gpg` or
`openssl` binary on `PATH`. Plaintext profiles do not.

## Quick Start

```bash
tokenctl profile init
tokenctl add --type github --name main --value 'ghp_xxx' --env-var GITHUB_TOKEN
tokenctl list
source <(tokenctl set --type github --name main --format export)
```

A child process cannot change the parent shell, so source the `export`
line. `--profile` goes before the subcommand and defaults to `default`:

```bash
source <(tokenctl --profile ci set --type github --name main --format export)
```

Names are unique within a type, so `main` can exist for both `github`
and `aws`. Selecting by `--name` also needs `--type`. `--id` selects a
token on its own. `--env-var` defaults to `TYPE_TOKEN` (for example
`GITHUB_TOKEN`).

## Command Reference

| Command                  | Purpose                                 |
| ------------------------ | --------------------------------------- |
| `list`                   | Print tokens as a table, JSON, or names |
| `types`                  | Print the token types in the profile    |
| `add`                    | Store a new token                       |
| `update`                 | Change type, name, value, or env var    |
| `delete`                 | Remove a token                          |
| `show`                   | Print metadata, or the value if asked   |
| `set`                    | Print export, dotenv, or the raw value  |
| `profile init`           | Create a profile and encryption mode    |
| `profile show`           | Print the profile name and encryption   |
| `profile set-encryption` | Rewrite tokens in a new encryption mode |
| `migrate`                | Copy or move tokens between profiles    |

### List and Show

```bash
tokenctl list
tokenctl list --type github --format names
tokenctl list --format json
tokenctl list --format json --reveal
tokenctl list --columns name,env_var,value --max-width 100
tokenctl types
tokenctl show --type github --name main
tokenctl show --type github --name main --reveal
```

The default list is a grouped text table. The table and JSON both hide
secret values unless you pass `--reveal`. `show` does the same.

`--columns` picks and orders columns. The names are `name`, `env_var`,
`id`, `updated`, `created`, `value`, and `type`. `--max-width` wraps the
table to that many characters.

### Add, Update, and Delete

```bash
tokenctl add --type pypi --name publish
printf '%s' 'pypi-secret' | tokenctl add --type pypi --name publish --value -
tokenctl update --type github --name main --new-name prod --value 'ghp_new'
tokenctl delete --type pypi --name publish
```

Omit `--value` on `add` and the tool prompts without echoing. `--value -`
reads the secret from stdin, which keeps it out of shell history and the
process list. On `update`, omit `--value` to leave the secret unchanged,
or pass `--value -` to replace it from stdin.

### Set

```bash
tokenctl set --type github --name prod --format export
tokenctl set --type pypi --name publish --format dotenv
tokenctl set --type github --name prod --format value
```

`export` is the default. Values are single-quoted for the shell.

### Profiles

```bash
tokenctl profile init
tokenctl --profile ci profile init --encryption openssl
tokenctl --profile ci profile show
tokenctl --profile ci profile set-encryption gpg
```

`set-encryption` rewrites the tokens in the new mode and removes the
previous token file, so a switch to encryption does not leave plaintext
behind.

### Migrate

```bash
tokenctl migrate --from-profile default --to-profile ci --dry-run
tokenctl migrate --from-profile default --to-profile ci --type github --name prod --move --overwrite
```

`--dry-run` prints the change and writes nothing. Without `--move`, the
source profile is left as it is. `--overwrite` replaces a destination
token that already uses the same type and name. A conflict without
`--overwrite` is still an error during a dry run.

## Storage and Encryption

Tokens live under `$XDG_CONFIG_HOME/tokenctl` (or `~/.config/tokenctl`).
Each profile is `profiles/<profile>/` with a `config.json` encryption
mode of `none`, `gpg`, or `openssl`.

| Mode      | File              | Tool                        |
| --------- | ----------------- | --------------------------- |
| `none`    | `tokens.json`     | Plaintext JSON, mode `0600` |
| `gpg`     | `tokens.json.gpg` | `gpg --symmetric` AES256    |
| `openssl` | `tokens.json.enc` | `openssl enc -aes-256-cbc`  |

Set `TOKENCTL_PASSPHRASE` for a non-interactive shell. On a terminal the
tool prompts, and that passphrase is passed to `gpg` or `openssl` on its
own pipe. It is not written into the environment. Files are written to a
temporary path and then replaced.

Each token stores `id`, `type`, `name`, `value`, `env_var`, `created_at`,
and `updated_at`. Timestamps are UTC in `YYYY-MM-DDTHH:MM:SSZ` form.

Exit `0` is success. Exit `1` is a runtime failure (missing token,
conflict, or crypto error). Exit `2` is a usage error, such as `--name`
without `--type`.

## Library

```python
from lupaxa.token_manager import Store

store = Store(profile="default")
for token in store.load():
    print(token.name, token.type)
```

`Store(profile, config_dir=...)` overrides the config root.

## Documentation

Site pages live in `mkdocs/` and publish to
<https://token-manager.thelupaxaproject.org/>.

```bash
make init
make python-install-dev
make mkdocs-serve
```

<a href="https://github.com/the-lupaxa-project">
    <img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/components/footer-for-child-orgs.svg" alt="The Lupaxa Project Footer" width="100%" />
</a>
