zecret 0.1.0__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.
Files changed (64) hide show
  1. zecret-0.1.0/.github/dependabot.yml +30 -0
  2. zecret-0.1.0/.github/workflows/ci.yml +121 -0
  3. zecret-0.1.0/.github/workflows/pages.yml +60 -0
  4. zecret-0.1.0/.github/workflows/release.yml +180 -0
  5. zecret-0.1.0/.gitignore +26 -0
  6. zecret-0.1.0/.python-version +1 -0
  7. zecret-0.1.0/CHANGELOG.md +77 -0
  8. zecret-0.1.0/LICENSE +21 -0
  9. zecret-0.1.0/PKG-INFO +242 -0
  10. zecret-0.1.0/README.md +215 -0
  11. zecret-0.1.0/SECURITY.md +75 -0
  12. zecret-0.1.0/assets/date-dark.png +0 -0
  13. zecret-0.1.0/assets/date-light.png +0 -0
  14. zecret-0.1.0/assets/editor-dark.png +0 -0
  15. zecret-0.1.0/assets/editor-light.png +0 -0
  16. zecret-0.1.0/assets/entries-dark.png +0 -0
  17. zecret-0.1.0/assets/entries-light.png +0 -0
  18. zecret-0.1.0/assets/help-dark.png +0 -0
  19. zecret-0.1.0/assets/help-light.png +0 -0
  20. zecret-0.1.0/assets/search-dark.png +0 -0
  21. zecret-0.1.0/assets/search-light.png +0 -0
  22. zecret-0.1.0/docs/CNAME +1 -0
  23. zecret-0.1.0/docs/index.html +524 -0
  24. zecret-0.1.0/pyproject.toml +163 -0
  25. zecret-0.1.0/src/zecret/__init__.py +11 -0
  26. zecret-0.1.0/src/zecret/__main__.py +41 -0
  27. zecret-0.1.0/src/zecret/app.py +197 -0
  28. zecret-0.1.0/src/zecret/app.tcss +288 -0
  29. zecret-0.1.0/src/zecret/config.py +112 -0
  30. zecret-0.1.0/src/zecret/crypto.py +192 -0
  31. zecret-0.1.0/src/zecret/models.py +113 -0
  32. zecret-0.1.0/src/zecret/py.typed +0 -0
  33. zecret-0.1.0/src/zecret/screens/__init__.py +1 -0
  34. zecret-0.1.0/src/zecret/screens/base.py +173 -0
  35. zecret-0.1.0/src/zecret/screens/confirm.py +46 -0
  36. zecret-0.1.0/src/zecret/screens/date_prompt.py +85 -0
  37. zecret-0.1.0/src/zecret/screens/editor.py +162 -0
  38. zecret-0.1.0/src/zecret/screens/entry_list.py +423 -0
  39. zecret-0.1.0/src/zecret/screens/header.py +69 -0
  40. zecret-0.1.0/src/zecret/screens/help.py +169 -0
  41. zecret-0.1.0/src/zecret/screens/search.py +140 -0
  42. zecret-0.1.0/src/zecret/screens/settings.py +251 -0
  43. zecret-0.1.0/src/zecret/screens/unlock.py +147 -0
  44. zecret-0.1.0/src/zecret/storage.py +610 -0
  45. zecret-0.1.0/tests/conftest.py +58 -0
  46. zecret-0.1.0/tests/test_chrome.py +203 -0
  47. zecret-0.1.0/tests/test_config.py +160 -0
  48. zecret-0.1.0/tests/test_crypto.py +349 -0
  49. zecret-0.1.0/tests/test_date_prompt_screen.py +168 -0
  50. zecret-0.1.0/tests/test_docs_page.py +164 -0
  51. zecret-0.1.0/tests/test_editor_screen.py +497 -0
  52. zecret-0.1.0/tests/test_entry_list_screen.py +870 -0
  53. zecret-0.1.0/tests/test_help_screen.py +281 -0
  54. zecret-0.1.0/tests/test_locking.py +357 -0
  55. zecret-0.1.0/tests/test_main.py +74 -0
  56. zecret-0.1.0/tests/test_models.py +282 -0
  57. zecret-0.1.0/tests/test_properties.py +260 -0
  58. zecret-0.1.0/tests/test_scale.py +144 -0
  59. zecret-0.1.0/tests/test_search_screen.py +328 -0
  60. zecret-0.1.0/tests/test_settings_screen.py +493 -0
  61. zecret-0.1.0/tests/test_storage.py +1087 -0
  62. zecret-0.1.0/tests/test_unlock_screen.py +326 -0
  63. zecret-0.1.0/tools/screenshots.py +218 -0
  64. zecret-0.1.0/uv.lock +1394 -0
@@ -0,0 +1,30 @@
1
+ version: 2
2
+
3
+ updates:
4
+ # Keep the workflow's actions current. Security fixes to actions land
5
+ # here, and pinned major versions otherwise drift out of support.
6
+ - package-ecosystem: github-actions
7
+ directory: /
8
+ schedule:
9
+ interval: weekly
10
+ commit-message:
11
+ prefix: "ci"
12
+
13
+ # Keep uv.lock current. This matters more than usual for Zecret: a
14
+ # cryptography or argon2-cffi advisory should surface as a pull request,
15
+ # not wait for someone to notice.
16
+ - package-ecosystem: uv
17
+ directory: /
18
+ schedule:
19
+ interval: weekly
20
+ commit-message:
21
+ prefix: "deps"
22
+ groups:
23
+ # One PR for routine dev-tool bumps; crypto dependencies stay
24
+ # separate so they get looked at on their own.
25
+ dev-tools:
26
+ patterns:
27
+ - ruff
28
+ - mypy
29
+ - pytest*
30
+ - textual-dev
@@ -0,0 +1,121 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ # Actions are pinned to full commit SHAs, with the version in a trailing
10
+ # comment. Tags are mutable and not every action publishes a floating major
11
+ # tag, so a SHA is both the reproducible choice and the one that cannot be
12
+ # repointed under us. Dependabot bumps these and rewrites the comment.
13
+
14
+ # Least privilege: nothing here writes to the repository.
15
+ permissions:
16
+ contents: read
17
+
18
+ # A new push to the same branch makes the previous run obsolete.
19
+ concurrency:
20
+ group: ${{ github.workflow }}-${{ github.ref }}
21
+ cancel-in-progress: true
22
+
23
+ env:
24
+ # Every uv command asserts uv.lock is present and current, and fails if
25
+ # pyproject.toml changed without re-locking. Set here rather than as a
26
+ # --locked flag so it covers `uv run` too, not just `uv sync`.
27
+ UV_LOCKED: "1"
28
+
29
+ jobs:
30
+ lint:
31
+ name: Lint and format
32
+ runs-on: ubuntu-latest
33
+ timeout-minutes: 10
34
+ steps:
35
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
36
+
37
+ - name: Install uv
38
+ uses: astral-sh/setup-uv@ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d # v10.0.0
39
+ with:
40
+ enable-cache: true
41
+ cache-dependency-glob: uv.lock
42
+
43
+ - name: Install dependencies
44
+ run: uv sync
45
+
46
+ - name: Ruff lint
47
+ run: uv run ruff check --output-format=github .
48
+
49
+ - name: Ruff format
50
+ run: uv run ruff format --check --diff .
51
+
52
+ types:
53
+ name: Type check
54
+ runs-on: ubuntu-latest
55
+ timeout-minutes: 10
56
+ steps:
57
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
58
+
59
+ - name: Install uv
60
+ uses: astral-sh/setup-uv@ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d # v10.0.0
61
+ with:
62
+ enable-cache: true
63
+ cache-dependency-glob: uv.lock
64
+
65
+ - name: Install dependencies
66
+ run: uv sync
67
+
68
+ - name: mypy
69
+ run: uv run mypy
70
+
71
+ test:
72
+ name: Test
73
+ runs-on: ubuntu-latest
74
+ timeout-minutes: 15
75
+ # No version matrix. `requires-python` is a floor rather than a pin, so
76
+ # newer interpreters are permitted, but 3.13 is the one every push is
77
+ # checked against -- testing the floor is what catches a symbol that
78
+ # only a later version has. Everything else here agrees: mypy's
79
+ # python_version and ruff's target-version both name 3.13 too.
80
+ steps:
81
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
82
+
83
+ # Named explicitly rather than left to .python-version, so that the
84
+ # interpreter CI runs on is visible in this file.
85
+ - name: Install uv
86
+ uses: astral-sh/setup-uv@ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d # v10.0.0
87
+ with:
88
+ enable-cache: true
89
+ cache-dependency-glob: uv.lock
90
+ python-version: "3.13"
91
+
92
+ - name: Install dependencies
93
+ run: uv sync
94
+
95
+ # --cov and `-m ""` here rather than in addopts: a local
96
+ # `uv run pytest` stays quick, skipping coverage and the scale tests,
97
+ # while neither can quietly erode on main. `-m ""` overrides the
98
+ # `-m "not slow"` default and selects everything; the coverage
99
+ # threshold lives in pyproject.toml under [tool.coverage.report].
100
+ - name: Run tests
101
+ run: uv run pytest -q --cov -m ""
102
+
103
+ # Catches packaging breakage the test suite cannot: the console
104
+ # script is only wired up when the project is actually installed.
105
+ - name: Smoke-test the entry point
106
+ run: uv run zecret --help
107
+
108
+ # A single required check to protect the branch with, so jobs can be
109
+ # added or removed without editing branch protection rules.
110
+ ci:
111
+ name: CI
112
+ if: always()
113
+ needs: [lint, types, test]
114
+ runs-on: ubuntu-latest
115
+ timeout-minutes: 5
116
+ steps:
117
+ - name: Fail if any job failed or was cancelled
118
+ if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
119
+ run: exit 1
120
+ - name: Success
121
+ run: echo "All checks passed."
@@ -0,0 +1,60 @@
1
+ name: Pages
2
+
3
+ # The product page at docs/index.html. Separate from CI on purpose: it has
4
+ # nothing to do with whether the code is sound, and a page typo should not
5
+ # read as a failing build on a commit that only touched prose.
6
+
7
+ on:
8
+ push:
9
+ branches: [main]
10
+ paths:
11
+ - docs/**
12
+ - .github/workflows/pages.yml
13
+ workflow_dispatch:
14
+
15
+ # Actions are pinned to full commit SHAs, with the version in a trailing
16
+ # comment, matching ci.yml. Dependabot bumps these and rewrites the comment.
17
+
18
+ # Least privilege: the build only reads the repository. The deploy job asks
19
+ # for the two extra scopes it needs, and nothing else inherits them.
20
+ permissions:
21
+ contents: read
22
+
23
+ # One deployment at a time, and never cancel one in flight: a half-finished
24
+ # deploy that gets cancelled leaves the live site on the old version with
25
+ # nothing queued to fix it. Superseded runs simply wait their turn.
26
+ concurrency:
27
+ group: pages
28
+ cancel-in-progress: false
29
+
30
+ jobs:
31
+ build:
32
+ name: Build site
33
+ runs-on: ubuntu-latest
34
+ timeout-minutes: 10
35
+ steps:
36
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
37
+
38
+ # No actions/configure-pages step: that exists to feed a base path
39
+ # into a static site generator and to auto-enable Pages. This is one
40
+ # hand-written file with relative links, so it would only be another
41
+ # pinned action to keep current.
42
+ - name: Upload docs/ as the site
43
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
44
+ with:
45
+ path: docs
46
+
47
+ deploy:
48
+ name: Deploy to GitHub Pages
49
+ needs: build
50
+ runs-on: ubuntu-latest
51
+ timeout-minutes: 10
52
+ permissions:
53
+ pages: write
54
+ id-token: write
55
+ environment:
56
+ name: github-pages
57
+ url: ${{ steps.deploy.outputs.page_url }}
58
+ steps:
59
+ - id: deploy
60
+ uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
@@ -0,0 +1,180 @@
1
+ name: Release
2
+
3
+ # Tags only. Pushing a `v*` tag publishes that version to PyPI and opens a
4
+ # GitHub release for it; nothing else triggers this. There is no manual
5
+ # dispatch on purpose -- a release should be a tag in the history, not a
6
+ # button someone pressed once.
7
+ on:
8
+ push:
9
+ tags: ["v*"]
10
+
11
+ # Actions are pinned to full commit SHAs, with the version in a trailing
12
+ # comment, exactly as in ci.yml. A mutable tag on a workflow that holds a
13
+ # publishing identity is the one place that would matter most.
14
+
15
+ # Least privilege by default; each job widens only what it needs.
16
+ permissions:
17
+ contents: read
18
+
19
+ env:
20
+ UV_LOCKED: "1"
21
+
22
+ jobs:
23
+ # The version in pyproject.toml and the tag being released have to agree.
24
+ # They are written in different places by different hands, and the failure
25
+ # is silent otherwise: PyPI would happily accept a tag naming one version
26
+ # while the package carries another, and the wrong number would be public
27
+ # and unrepublishable.
28
+ check:
29
+ name: Check the tag matches the version
30
+ runs-on: ubuntu-latest
31
+ timeout-minutes: 5
32
+ steps:
33
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
34
+
35
+ - name: Compare
36
+ run: |
37
+ set -euo pipefail
38
+ tag="${GITHUB_REF_NAME#v}"
39
+ version="$(python3 -c 'import tomllib,pathlib; print(tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"])')"
40
+ echo "tag=$tag pyproject=$version"
41
+ if [ "$tag" != "$version" ]; then
42
+ echo "::error::tag $GITHUB_REF_NAME does not match pyproject version $version"
43
+ exit 1
44
+ fi
45
+
46
+ # CI runs on every push to main, but a tag can be pushed at any commit, so
47
+ # the checks are run again here against exactly what is about to ship.
48
+ verify:
49
+ name: Test before publishing
50
+ needs: [check]
51
+ runs-on: ubuntu-latest
52
+ timeout-minutes: 15
53
+ steps:
54
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
55
+
56
+ - name: Install uv
57
+ uses: astral-sh/setup-uv@ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d # v10.0.0
58
+ with:
59
+ enable-cache: true
60
+ cache-dependency-glob: uv.lock
61
+ python-version: "3.13"
62
+
63
+ - name: Install dependencies
64
+ run: uv sync
65
+
66
+ - name: Lint, types, tests
67
+ run: |
68
+ uv run ruff check .
69
+ uv run ruff format --check .
70
+ uv run mypy
71
+ uv run pytest -q --cov -m ""
72
+
73
+ pypi:
74
+ name: Publish to PyPI
75
+ needs: [verify]
76
+ runs-on: ubuntu-latest
77
+ timeout-minutes: 10
78
+ # Trusted Publishing (OIDC): PyPI is configured to trust this repository
79
+ # and this workflow filename, so there is no API token anywhere in the
80
+ # repo or its secrets. `id-token: write` is what mints the short-lived
81
+ # credential; it is granted here and nowhere else.
82
+ permissions:
83
+ contents: read
84
+ id-token: write
85
+ # Named so PyPI's pending publisher can require it, and so a release can
86
+ # be gated behind a reviewer in the repository's environment settings.
87
+ environment:
88
+ name: pypi
89
+ url: https://pypi.org/p/zecret
90
+ steps:
91
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
92
+
93
+ - name: Install uv
94
+ uses: astral-sh/setup-uv@ae62891fec2bb8e7d6c99fc78c9fec3a63790f8d # v10.0.0
95
+ with:
96
+ enable-cache: true
97
+ cache-dependency-glob: uv.lock
98
+ python-version: "3.13"
99
+
100
+ - name: Build the sdist and wheel
101
+ run: uv build
102
+
103
+ # What goes up is worth looking at in the log: the sdist should hold
104
+ # the project and not the working tree, and the wheel needs app.tcss
105
+ # and py.typed or the installed program is broken in ways no test here
106
+ # would catch.
107
+ - name: Show what is about to be published
108
+ run: |
109
+ set -euo pipefail
110
+ for f in dist/*.tar.gz; do echo "== $f"; tar tzf "$f"; done
111
+ for f in dist/*.whl; do echo "== $f"; unzip -l "$f"; done
112
+
113
+ - name: Publish
114
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
115
+
116
+ github-release:
117
+ name: Open the GitHub release
118
+ needs: [pypi]
119
+ runs-on: ubuntu-latest
120
+ timeout-minutes: 5
121
+ # The only job that writes to the repository, and all it writes is a
122
+ # release. Deliberately after PyPI: a release pointing at a version that
123
+ # failed to publish is worse than no release yet.
124
+ permissions:
125
+ contents: write
126
+ steps:
127
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
128
+
129
+ # A release page is read, not clicked through, so it carries the
130
+ # changelog section itself rather than a link to it. CHANGELOG.md stays
131
+ # the one place the words are written; this only lifts them out, and
132
+ # fails the release rather than publishing empty notes if the section
133
+ # for this tag is missing.
134
+ - name: Build the release notes
135
+ env:
136
+ TAG: ${{ github.ref_name }}
137
+ run: |
138
+ set -euo pipefail
139
+ version="${TAG#v}"
140
+ # From this version's heading to the next one, stopping short of
141
+ # the link definitions at the foot of the file. Matched by string
142
+ # rather than regex: a version is full of dots, and every one of
143
+ # them is a wildcard that would match a different release.
144
+ awk -v v="$version" '
145
+ index($0, "## [" v "]") == 1 { inside = 1; next }
146
+ inside && /^## / { exit }
147
+ inside && /^\[[^]]+\]: / { exit }
148
+ inside { print }
149
+ ' CHANGELOG.md > notes.md
150
+
151
+ if ! grep -q '[^[:space:]]' notes.md; then
152
+ echo "::error::CHANGELOG.md has no section for $version"
153
+ exit 1
154
+ fi
155
+
156
+ # Relative links resolve against the releases URL rather than the
157
+ # repository root, so they would 404 on the release page. Point
158
+ # them at this tag instead.
159
+ sed -i "s#](\([A-Za-z][A-Za-z0-9_.-]*\.md\))#](https://github.com/${GITHUB_REPOSITORY}/blob/${TAG}/\1)#g" notes.md
160
+
161
+ {
162
+ echo
163
+ echo "---"
164
+ echo
165
+ echo "Install with \`uv tool install zecret\`, or \`pipx install zecret\` on Python 3.13 or newer."
166
+ } >> notes.md
167
+
168
+ echo "--- notes.md ---"
169
+ cat notes.md
170
+
171
+ # `gh` is preinstalled on the runner, so this needs no third-party
172
+ # action -- one less thing holding a token.
173
+ - name: Create the release
174
+ env:
175
+ GH_TOKEN: ${{ github.token }}
176
+ run: |
177
+ gh release create "$GITHUB_REF_NAME" \
178
+ --title "$GITHUB_REF_NAME" \
179
+ --notes-file notes.md \
180
+ --verify-tag
@@ -0,0 +1,26 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ venv/
6
+ .pytest_cache/
7
+ .mypy_cache/
8
+ .ruff_cache/
9
+ # Hypothesis's example database: machine-local, and regenerated on demand.
10
+ .hypothesis/
11
+ dist/
12
+ build/
13
+ # Diary files -- never commit one, encrypted or not.
14
+ *.enc
15
+ .zecret/
16
+
17
+ # uv.lock is deliberately NOT ignored: Zecret is an application, not a
18
+ # library, so the lockfile is committed to pin exact dependency versions.
19
+ # CI installs with `uv sync --locked`, which needs it present and current.
20
+
21
+ # IDE and coverage artifacts
22
+ .idea/
23
+ .vscode/
24
+ .coverage
25
+ coverage.xml
26
+ htmlcov/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,77 @@
1
+ # Changelog
2
+
3
+ Notable changes to Zecret, newest first. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions
5
+ follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ Anything that changes the on-disk format gets its own heading here, with
8
+ what it means for a diary written by an older version. Nothing else in this
9
+ file matters as much as that does.
10
+
11
+ ## [Unreleased]
12
+
13
+ ## [0.1.0] - 2026-08-17
14
+
15
+ The first release. What follows is what Zecret does on its first day rather
16
+ than a list of changes from something earlier: the entries that tracked its
17
+ development described a program nobody outside had run, so they have been
18
+ folded into this one and left in the git history, where they belong.
19
+
20
+ A `0.x` version on purpose. The program is finished and tested, but no one
21
+ has yet kept a diary in it for a year, and the keys and the command line
22
+ should stay free to move until someone has. The **file format is a
23
+ different promise, and it is already made**: it is version 1, and a diary
24
+ written today will be readable by every later Zecret or migrated by one.
25
+
26
+ ### Added
27
+
28
+ - **A diary of days.** One entry per calendar day, and the date is the
29
+ entry's whole identity — no titles, no ids, nothing to name or file.
30
+ Opening a day means writing it or continuing what is already there. The
31
+ day is the local one, so something written at 23:50 belongs to the day
32
+ you would call it.
33
+ - **A master password and nothing else.** Argon2id derives the key
34
+ (time_cost 3, 64 MiB, 4 lanes) and every entry is sealed on its own with
35
+ AES-256-GCM. Editing one day never re-encrypts another. A wrong password
36
+ or an altered file fails loudly rather than returning nonsense — and
37
+ there is no recovery, by design. Nobody, including you, opens the file
38
+ without the password.
39
+ - **The diary locks itself.** After fifteen minutes without a keystroke
40
+ Zecret forgets the diary and the key and asks for the password again;
41
+ `L` does it on demand. A half-written entry holds the lock off rather
42
+ than being discarded by a timer, and the wait is configurable, including
43
+ turning it off.
44
+ - **Search across every entry**, filtering as you type, with no separate
45
+ step to submit.
46
+ - **An entry list that stays usable at years of writing.** Days are grouped
47
+ under month headings, newest first; `j`/`k` move a day, `g`/`G` and
48
+ `home`/`end` jump to the newest and oldest, and the page keys move a
49
+ screenful.
50
+ - **Every key documented in the app.** `?` lists all of them, generated
51
+ from the bindings themselves, so the popup cannot fall out of step with
52
+ what the program actually does. The footer shows the seven that fit an
53
+ 80-column terminal; the rest are a keypress away.
54
+ - **Themes**, chosen in settings and remembered between runs in
55
+ `~/.zecret/config.json` — the one file Zecret writes in the clear, and it
56
+ holds preferences and nothing else. No entry text, no dates, nothing
57
+ derived from your key.
58
+ - **Writes that do not lose a diary.** Saves go to a temporary file in the
59
+ same directory, are fsynced, and replace the real one in a single
60
+ indivisible step. A second Zecret writing the same file is detected and
61
+ refused rather than silently overwritten, and `r` re-reads without asking
62
+ for the password again. Creating a diary claims the path in the same step
63
+ that writes it, so two first runs cannot race.
64
+ - **A diary anywhere you like.** `~/.zecret/diary.enc` by default,
65
+ `--path` or `ZECRET_DIARY_PATH` for somewhere else — separate diaries, or
66
+ a throwaway one to try it with.
67
+
68
+ ### Security
69
+
70
+ - The threat model, what counts as a vulnerability, and how to report one
71
+ privately are written down in [SECURITY.md](SECURITY.md), along with the
72
+ properties that are known and accepted rather than bugs. Chief among
73
+ them: the file reveals *which days* have entries, though not a word of
74
+ what they say.
75
+
76
+ [Unreleased]: https://github.com/kfurtak1024/zecret/compare/v0.1.0...HEAD
77
+ [0.1.0]: https://github.com/kfurtak1024/zecret/releases/tag/v0.1.0
zecret-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Krzysztof Furtak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.