pikuri-thunderbird 0.1.0
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.
- checksums.yaml +7 -0
- data/DESIGN.md +460 -0
- data/README.md +66 -0
- data/lib/pikuri/thunderbird/calendar.rb +372 -0
- data/lib/pikuri/thunderbird/calendar_create.rb +126 -0
- data/lib/pikuri/thunderbird/calendar_read.rb +130 -0
- data/lib/pikuri/thunderbird/calendar_search.rb +145 -0
- data/lib/pikuri/thunderbird/compose_guard.rb +281 -0
- data/lib/pikuri/thunderbird/contact_search.rb +90 -0
- data/lib/pikuri/thunderbird/database_snapshot.rb +155 -0
- data/lib/pikuri/thunderbird/date_helpers.rb +93 -0
- data/lib/pikuri/thunderbird/extension.rb +196 -0
- data/lib/pikuri/thunderbird/gloda/contacts.rb +229 -0
- data/lib/pikuri/thunderbird/gloda/mail.rb +216 -0
- data/lib/pikuri/thunderbird/gloda.rb +153 -0
- data/lib/pikuri/thunderbird/ical_line.rb +130 -0
- data/lib/pikuri/thunderbird/ics_event.rb +131 -0
- data/lib/pikuri/thunderbird/launcher.rb +76 -0
- data/lib/pikuri/thunderbird/mail_compose.rb +92 -0
- data/lib/pikuri/thunderbird/mail_read.rb +73 -0
- data/lib/pikuri/thunderbird/mail_search.rb +131 -0
- data/lib/pikuri/thunderbird/mailto_uri.rb +58 -0
- data/lib/pikuri/thunderbird/profile.rb +201 -0
- data/lib/pikuri-thunderbird.rb +76 -0
- data/prompts/thunderbird.txt +5 -0
- metadata +114 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'pikuri-core'
|
|
4
|
+
|
|
5
|
+
# Entry file for the pikuri-thunderbird gem: local Thunderbird mail +
|
|
6
|
+
# calendar search/read for a pikuri agent, home of the
|
|
7
|
+
# +bin/pikuri-thunderbird+ no-egress demo. {Pikuri::Thunderbird::Extension}
|
|
8
|
+
# is the one-call wiring; it reads Thunderbird's own on-disk profile
|
|
9
|
+
# ({Pikuri::Thunderbird::Profile} discovers it) and never touches the
|
|
10
|
+
# network.
|
|
11
|
+
#
|
|
12
|
+
# The load-bearing posture (v1): search + read are inbound-only, so an
|
|
13
|
+
# agent wired with only these tools has private data + untrusted content
|
|
14
|
+
# but *no egress leg* — the lethal trifecta is broken by construction, the
|
|
15
|
+
# same model as +bin/pikuri-corpus+. Outbound actions (compose / create
|
|
16
|
+
# event) are v2 and are always human-gated hand-offs to Thunderbird's own
|
|
17
|
+
# UI. Threat model: +DESIGN.md+; design rationale: +ideas/thunderbird.md+.
|
|
18
|
+
Pikuri::PROMPT_DIRS << File.expand_path('../prompts', __dir__)
|
|
19
|
+
|
|
20
|
+
module Pikuri
|
|
21
|
+
module Thunderbird
|
|
22
|
+
# Legs of the five inbound tools: a mailbox and a calendar are private by
|
|
23
|
+
# *domain*, and their contents are written by whoever mailed you.
|
|
24
|
+
#
|
|
25
|
+
# The +private: true+ is the one place the framework declares that leg for
|
|
26
|
+
# you, and it is a narrow exception rather than a breach of the rule that
|
|
27
|
+
# the user declares sensitivity: elsewhere the framework cannot tell
|
|
28
|
+
# +~/work/scratch+ from +~/work/payroll+, but a *mailbox* is sensitive by
|
|
29
|
+
# what it is, not by how it was configured. Nothing was inspected to know
|
|
30
|
+
# this — only the tool's domain.
|
|
31
|
+
#
|
|
32
|
+
# @return [Pikuri::Tool::TrifectaLegs]
|
|
33
|
+
INBOUND_LEGS = Pikuri::Tool::TrifectaLegs.new(
|
|
34
|
+
private: true, untrusted: :hard, egress_payload_review: :no_egress
|
|
35
|
+
).freeze
|
|
36
|
+
|
|
37
|
+
# Legs of the two opt-in outbound hand-offs.
|
|
38
|
+
#
|
|
39
|
+
# +:human_reviewed+ rather than +:unreviewed+ because all four clauses of
|
|
40
|
+
# the approver seat hold, and the load-bearing one is payload visibility:
|
|
41
|
+
# the human commits in Thunderbird's own compose window / import wizard, so
|
|
42
|
+
# what is on screen *is* what leaves, byte for byte. That is why these are
|
|
43
|
+
# graded differently from a confirmer-gated shell command, where the human
|
|
44
|
+
# approves a program whose output was never shown.
|
|
45
|
+
#
|
|
46
|
+
# The destination stays +:attacker_reachable+, and the pair is the clearest
|
|
47
|
+
# proof the two egress axes are orthogonal: the recipient is a drafted
|
|
48
|
+
# field, so an injection can address the mail to itself and a reviewed
|
|
49
|
+
# payload still lands in an inbox the attacker reads.
|
|
50
|
+
#
|
|
51
|
+
# It stays true only while the outbound surface carries nothing but fields
|
|
52
|
+
# that render literally — no attachments, no HTML body. A tool that gained
|
|
53
|
+
# one would silently drop to hard +:egress+, since the human would be
|
|
54
|
+
# approving a reference to bytes nobody saw.
|
|
55
|
+
#
|
|
56
|
+
# No +private+, unlike {INBOUND_LEGS}: these *send*, they do not read the
|
|
57
|
+
# mailbox. The one trickle back is {ComposeGuard}'s recipient-novelty note,
|
|
58
|
+
# and it is a single incidental bit about an address the model itself
|
|
59
|
+
# supplied — worthless under attack, where a novel recipient is expected by
|
|
60
|
+
# construction. The private leg grades what a tool lets an attacker
|
|
61
|
+
# **query** over the pool, not whether any bit at all flows back.
|
|
62
|
+
#
|
|
63
|
+
# @return [Pikuri::Tool::TrifectaLegs]
|
|
64
|
+
OUTBOUND_LEGS = Pikuri::Tool::TrifectaLegs.new(
|
|
65
|
+
private: false, untrusted: :none,
|
|
66
|
+
egress_payload_review: :human_reviewed, egress_destination: :attacker_reachable
|
|
67
|
+
).freeze
|
|
68
|
+
|
|
69
|
+
LOADER = Zeitwerk::Loader.new
|
|
70
|
+
LOADER.tag = 'pikuri-thunderbird'
|
|
71
|
+
LOADER.push_dir(__dir__)
|
|
72
|
+
LOADER.ignore(File.expand_path('pikuri-thunderbird.rb', __dir__))
|
|
73
|
+
LOADER.setup
|
|
74
|
+
LOADER.eager_load
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
You are a helpful assistant for the user's own local Thunderbird data — their
|
|
2
|
+
stored mail and their calendars. You help them find messages and events, recall
|
|
3
|
+
what was said, and answer questions grounded in what is actually there.
|
|
4
|
+
|
|
5
|
+
Be concise. Lead with the answer, then the supporting details.
|
metadata
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: pikuri-thunderbird
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Martin Vysny
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: pikuri-core
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - '='
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.1.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - '='
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 0.1.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: sqlite3
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.9'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.9'
|
|
40
|
+
description: |
|
|
41
|
+
pikuri-thunderbird lets a pikuri agent search and read the user's
|
|
42
|
+
*local* Thunderbird data — mail folders and cached calendars — by
|
|
43
|
+
reading Thunderbird's own on-disk profile. It never speaks
|
|
44
|
+
IMAP/POP3/SMTP itself and never egresses: search and read are both
|
|
45
|
+
inbound-only, so the v1 demo (+bin/pikuri-thunderbird+) breaks the
|
|
46
|
+
lethal trifecta by construction, exactly like +bin/pikuri-corpus+.
|
|
47
|
+
|
|
48
|
+
Mail search rides Thunderbird's Gloda index
|
|
49
|
+
(+global-messages-db.sqlite+) as a pre-decoded corpus: pikuri copies a
|
|
50
|
+
consistent snapshot, builds its own ephemeral FTS5 index over the
|
|
51
|
+
decoded columns, and serves ranked search + full-body reads with no
|
|
52
|
+
MIME parsing. Calendar reads come from the +calendar-data/*.sqlite+
|
|
53
|
+
stores (normalized columns, no ICS parser for the common case).
|
|
54
|
+
|
|
55
|
+
Any *outbound* action (compose a mail, create an event) is a v2
|
|
56
|
+
feature and is always a human-gated hand-off to Thunderbird's own UI —
|
|
57
|
+
pikuri writes nothing to Thunderbird's stores and sends nothing itself.
|
|
58
|
+
See +pikuri-thunderbird/DESIGN.md+ and +ideas/thunderbird.md+.
|
|
59
|
+
email:
|
|
60
|
+
- martin@vysny.me
|
|
61
|
+
executables: []
|
|
62
|
+
extensions: []
|
|
63
|
+
extra_rdoc_files: []
|
|
64
|
+
files:
|
|
65
|
+
- DESIGN.md
|
|
66
|
+
- README.md
|
|
67
|
+
- lib/pikuri-thunderbird.rb
|
|
68
|
+
- lib/pikuri/thunderbird/calendar.rb
|
|
69
|
+
- lib/pikuri/thunderbird/calendar_create.rb
|
|
70
|
+
- lib/pikuri/thunderbird/calendar_read.rb
|
|
71
|
+
- lib/pikuri/thunderbird/calendar_search.rb
|
|
72
|
+
- lib/pikuri/thunderbird/compose_guard.rb
|
|
73
|
+
- lib/pikuri/thunderbird/contact_search.rb
|
|
74
|
+
- lib/pikuri/thunderbird/database_snapshot.rb
|
|
75
|
+
- lib/pikuri/thunderbird/date_helpers.rb
|
|
76
|
+
- lib/pikuri/thunderbird/extension.rb
|
|
77
|
+
- lib/pikuri/thunderbird/gloda.rb
|
|
78
|
+
- lib/pikuri/thunderbird/gloda/contacts.rb
|
|
79
|
+
- lib/pikuri/thunderbird/gloda/mail.rb
|
|
80
|
+
- lib/pikuri/thunderbird/ical_line.rb
|
|
81
|
+
- lib/pikuri/thunderbird/ics_event.rb
|
|
82
|
+
- lib/pikuri/thunderbird/launcher.rb
|
|
83
|
+
- lib/pikuri/thunderbird/mail_compose.rb
|
|
84
|
+
- lib/pikuri/thunderbird/mail_read.rb
|
|
85
|
+
- lib/pikuri/thunderbird/mail_search.rb
|
|
86
|
+
- lib/pikuri/thunderbird/mailto_uri.rb
|
|
87
|
+
- lib/pikuri/thunderbird/profile.rb
|
|
88
|
+
- prompts/thunderbird.txt
|
|
89
|
+
homepage: https://codeberg.org/mvysny/pikuri
|
|
90
|
+
licenses:
|
|
91
|
+
- MIT
|
|
92
|
+
metadata:
|
|
93
|
+
source_code_uri: https://codeberg.org/mvysny/pikuri/src/branch/master
|
|
94
|
+
changelog_uri: https://codeberg.org/mvysny/pikuri/src/branch/master/CHANGELOG.md
|
|
95
|
+
bug_tracker_uri: https://codeberg.org/mvysny/pikuri/issues
|
|
96
|
+
rubygems_mfa_required: 'true'
|
|
97
|
+
rdoc_options: []
|
|
98
|
+
require_paths:
|
|
99
|
+
- lib
|
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '3.3'
|
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
110
|
+
requirements: []
|
|
111
|
+
rubygems_version: 3.6.7
|
|
112
|
+
specification_version: 4
|
|
113
|
+
summary: Local Thunderbird mail + calendar tools for pikuri.
|
|
114
|
+
test_files: []
|