tokra 0.0.1.pre.1
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/.pre-commit-config.yaml +16 -0
- data/AGENTS.md +126 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +16 -0
- data/Cargo.toml +23 -0
- data/LICENSE +661 -0
- data/LICENSES/AGPL-3.0-or-later.txt +235 -0
- data/LICENSES/Apache-2.0.txt +73 -0
- data/LICENSES/CC-BY-SA-4.0.txt +170 -0
- data/LICENSES/CC0-1.0.txt +121 -0
- data/LICENSES/MIT.txt +18 -0
- data/README.md +45 -0
- data/README.rdoc +4 -0
- data/REUSE.toml +11 -0
- data/Rakefile +27 -0
- data/Steepfile +15 -0
- data/clippy.toml +5 -0
- data/clippy_exceptions.rb +59 -0
- data/doc/contributors/adr/001.md +187 -0
- data/doc/contributors/adr/002.md +132 -0
- data/doc/contributors/adr/003.md +116 -0
- data/doc/contributors/chats/001.md +3874 -0
- data/doc/contributors/plan/001.md +271 -0
- data/examples/verify_hello_world/app.rb +114 -0
- data/examples/verify_hello_world/index.html +88 -0
- data/examples/verify_ping_pong/README.md +0 -0
- data/examples/verify_ping_pong/app.rb +132 -0
- data/examples/verify_ping_pong/public/styles.css +182 -0
- data/examples/verify_ping_pong/views/index.erb +94 -0
- data/examples/verify_ping_pong/views/layout.erb +22 -0
- data/exe/semantic-highlight +0 -0
- data/ext/tokra/Cargo.toml +23 -0
- data/ext/tokra/extconf.rb +12 -0
- data/ext/tokra/src/lib.rs +719 -0
- data/lib/tokra/native.rb +79 -0
- data/lib/tokra/rack/handler.rb +177 -0
- data/lib/tokra/version.rb +12 -0
- data/lib/tokra.rb +19 -0
- data/mise.toml +8 -0
- data/rustfmt.toml +4 -0
- data/sig/tokra.rbs +7 -0
- data/tasks/lint.rake +151 -0
- data/tasks/rust.rake +63 -0
- data/tasks/steep.rake +11 -0
- data/tasks/test.rake +26 -0
- data/test_native.rb +37 -0
- data/vendor/goodcop/base.yml +1047 -0
- metadata +112 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/*
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
*/
|
|
6
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; }
|
|
7
|
+
|
|
8
|
+
:root {
|
|
9
|
+
--text: oklch(25% 0.02 250);
|
|
10
|
+
--text-muted: oklch(50% 0.015 250);
|
|
11
|
+
--surface: oklch(98% 0.005 250);
|
|
12
|
+
--border: oklch(88% 0.01 250);
|
|
13
|
+
--accent: oklch(55% 0.18 150);
|
|
14
|
+
--accent-bg: oklch(95% 0.04 150);
|
|
15
|
+
--warn: oklch(55% 0.16 30);
|
|
16
|
+
--warn-bg: oklch(95% 0.04 30);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
html {
|
|
20
|
+
font-family: 'Instrument Sans', system-ui, sans-serif;
|
|
21
|
+
font-size: clamp(0.95rem, 0.9rem + 0.25vw, 1.0625rem);
|
|
22
|
+
line-height: 1.5;
|
|
23
|
+
color: var(--text);
|
|
24
|
+
background: var(--surface);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
min-height: 100dvh;
|
|
29
|
+
display: grid;
|
|
30
|
+
place-items: center;
|
|
31
|
+
padding: clamp(1.5rem, 4vw, 3rem);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
main {
|
|
35
|
+
width: 100%;
|
|
36
|
+
max-width: 28rem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
h1 {
|
|
40
|
+
font-size: 1.5rem;
|
|
41
|
+
font-weight: 600;
|
|
42
|
+
letter-spacing: -0.01em;
|
|
43
|
+
margin-block-end: 1.5rem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Message from Ruby */
|
|
47
|
+
.message-block {
|
|
48
|
+
padding: 1rem 1.25rem;
|
|
49
|
+
background: oklch(96% 0.008 250);
|
|
50
|
+
border-left: 3px solid var(--border);
|
|
51
|
+
margin-block-end: 2rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.message-label {
|
|
55
|
+
font-size: 0.75rem;
|
|
56
|
+
font-weight: 500;
|
|
57
|
+
text-transform: uppercase;
|
|
58
|
+
letter-spacing: 0.05em;
|
|
59
|
+
color: var(--text-muted);
|
|
60
|
+
margin-block-end: 0.25rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.message-content {
|
|
64
|
+
font-size: 1.125rem;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* Form */
|
|
68
|
+
.field {
|
|
69
|
+
margin-block-end: 1.5rem;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
label {
|
|
73
|
+
display: block;
|
|
74
|
+
font-size: 0.875rem;
|
|
75
|
+
font-weight: 500;
|
|
76
|
+
margin-block-end: 0.375rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
input[type="text"] {
|
|
80
|
+
width: 100%;
|
|
81
|
+
padding: 0.625rem 0.75rem;
|
|
82
|
+
font-family: inherit;
|
|
83
|
+
font-size: 1rem;
|
|
84
|
+
color: var(--text);
|
|
85
|
+
background: white;
|
|
86
|
+
border: 1px solid var(--border);
|
|
87
|
+
border-radius: 6px;
|
|
88
|
+
outline: none;
|
|
89
|
+
transition: border-color 0.15s;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
input[type="text"]:focus {
|
|
93
|
+
border-color: var(--accent);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Actions */
|
|
97
|
+
.actions {
|
|
98
|
+
display: flex;
|
|
99
|
+
flex-wrap: wrap;
|
|
100
|
+
gap: 0.5rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
button {
|
|
104
|
+
padding: 0.5rem 1rem;
|
|
105
|
+
font-family: inherit;
|
|
106
|
+
font-size: 0.875rem;
|
|
107
|
+
font-weight: 500;
|
|
108
|
+
color: var(--text);
|
|
109
|
+
background: white;
|
|
110
|
+
border: 1px solid var(--border);
|
|
111
|
+
border-radius: 6px;
|
|
112
|
+
cursor: pointer;
|
|
113
|
+
transition: background 0.1s, border-color 0.1s;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
button:hover {
|
|
117
|
+
background: oklch(96% 0.005 250);
|
|
118
|
+
border-color: oklch(80% 0.01 250);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
button:active {
|
|
122
|
+
background: oklch(94% 0.008 250);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
button[data-primary] {
|
|
126
|
+
color: white;
|
|
127
|
+
background: var(--accent);
|
|
128
|
+
border-color: var(--accent);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
button[data-primary]:hover {
|
|
132
|
+
background: oklch(50% 0.18 150);
|
|
133
|
+
border-color: oklch(50% 0.18 150);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* Status feedback */
|
|
137
|
+
.feedback {
|
|
138
|
+
margin-block-start: 1.5rem;
|
|
139
|
+
padding: 0.75rem 1rem;
|
|
140
|
+
font-size: 0.875rem;
|
|
141
|
+
border-radius: 6px;
|
|
142
|
+
display: none;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.feedback[data-visible] {
|
|
146
|
+
display: block;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.feedback[data-type="success"] {
|
|
150
|
+
color: var(--accent);
|
|
151
|
+
background: var(--accent-bg);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.feedback[data-type="error"] {
|
|
155
|
+
color: var(--warn);
|
|
156
|
+
background: var(--warn-bg);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.feedback[data-type="pending"] {
|
|
160
|
+
color: var(--text-muted);
|
|
161
|
+
background: oklch(96% 0.005 250);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* IPC status indicator */
|
|
165
|
+
.ipc-indicator {
|
|
166
|
+
margin-block-start: 2rem;
|
|
167
|
+
padding-block-start: 1.5rem;
|
|
168
|
+
border-top: 1px solid var(--border);
|
|
169
|
+
font-size: 0.8rem;
|
|
170
|
+
color: var(--text-muted);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.ipc-indicator::before {
|
|
174
|
+
content: '';
|
|
175
|
+
display: inline-block;
|
|
176
|
+
width: 6px;
|
|
177
|
+
height: 6px;
|
|
178
|
+
background: var(--accent);
|
|
179
|
+
border-radius: 50%;
|
|
180
|
+
margin-inline-end: 0.5rem;
|
|
181
|
+
vertical-align: middle;
|
|
182
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
-->
|
|
6
|
+
<h1>Verification Test</h1>
|
|
7
|
+
|
|
8
|
+
<div class="message-block">
|
|
9
|
+
<div class="message-label">Message from Ruby</div>
|
|
10
|
+
<div class="message-content"><%= message %></div>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div class="field">
|
|
14
|
+
<label for="response">Your response</label>
|
|
15
|
+
<input type="text" id="response" name="response" autocomplete="off">
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="actions">
|
|
19
|
+
<button data-primary id="btn-ipc">Send via IPC</button>
|
|
20
|
+
<button id="btn-form">Submit form</button>
|
|
21
|
+
<button id="btn-fetch">POST to API</button>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="feedback" id="feedback"></div>
|
|
25
|
+
|
|
26
|
+
<% if flash["success"] %>
|
|
27
|
+
<div class="feedback" data-visible data-type="success"><%= flash["success"] %></div>
|
|
28
|
+
<% end %>
|
|
29
|
+
|
|
30
|
+
<div class="ipc-indicator" id="ipc-status">IPC available</div>
|
|
31
|
+
|
|
32
|
+
<script>
|
|
33
|
+
const responseInput = document.getElementById('response');
|
|
34
|
+
const feedback = document.getElementById('feedback');
|
|
35
|
+
const ipcStatus = document.getElementById('ipc-status');
|
|
36
|
+
|
|
37
|
+
function showFeedback(message, type) {
|
|
38
|
+
feedback.textContent = message;
|
|
39
|
+
feedback.setAttribute('data-type', type);
|
|
40
|
+
feedback.setAttribute('data-visible', '');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// IPC
|
|
44
|
+
document.getElementById('btn-ipc').addEventListener('click', () => {
|
|
45
|
+
const value = responseInput.value;
|
|
46
|
+
if (window.ipc) {
|
|
47
|
+
window.ipc.postMessage(value);
|
|
48
|
+
showFeedback('Sent via IPC: ' + value, 'success');
|
|
49
|
+
} else {
|
|
50
|
+
showFeedback('IPC not available', 'error');
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Form submit
|
|
55
|
+
document.getElementById('btn-form').addEventListener('click', () => {
|
|
56
|
+
const value = responseInput.value;
|
|
57
|
+
showFeedback('Submitting form...', 'pending');
|
|
58
|
+
|
|
59
|
+
const form = document.createElement('form');
|
|
60
|
+
form.method = 'POST';
|
|
61
|
+
form.action = 'tokra://localhost/submit';
|
|
62
|
+
const input = document.createElement('input');
|
|
63
|
+
input.type = 'hidden';
|
|
64
|
+
input.name = 'response';
|
|
65
|
+
input.value = value;
|
|
66
|
+
form.appendChild(input);
|
|
67
|
+
document.body.appendChild(form);
|
|
68
|
+
form.submit();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Fetch API
|
|
72
|
+
document.getElementById('btn-fetch').addEventListener('click', async () => {
|
|
73
|
+
const value = responseInput.value;
|
|
74
|
+
showFeedback('Sending request...', 'pending');
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
const response = await fetch('tokra://localhost/api', {
|
|
78
|
+
method: 'POST',
|
|
79
|
+
headers: { 'Content-Type': 'application/json' },
|
|
80
|
+
body: JSON.stringify({ message: value })
|
|
81
|
+
});
|
|
82
|
+
const data = await response.json();
|
|
83
|
+
showFeedback('Response: ' + JSON.stringify(data), 'success');
|
|
84
|
+
} catch (err) {
|
|
85
|
+
showFeedback('Request failed: ' + err.message, 'error');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// IPC availability
|
|
90
|
+
if (!window.ipc) {
|
|
91
|
+
ipcStatus.textContent = 'IPC unavailable';
|
|
92
|
+
ipcStatus.style.setProperty('--accent', 'var(--warn)');
|
|
93
|
+
}
|
|
94
|
+
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
3
|
+
|
|
4
|
+
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
-->
|
|
6
|
+
<!DOCTYPE html>
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="utf-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
11
|
+
<title>Tokra Verification</title>
|
|
12
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
13
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
14
|
+
<link href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600&display=swap" rel="stylesheet">
|
|
15
|
+
<link rel="stylesheet" href="tokra://localhost/styles.css">
|
|
16
|
+
</head>
|
|
17
|
+
<body>
|
|
18
|
+
<main>
|
|
19
|
+
<%== yield %>
|
|
20
|
+
</main>
|
|
21
|
+
</body>
|
|
22
|
+
</html>
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
[package]
|
|
6
|
+
name = "tokra"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
edition = "2021"
|
|
9
|
+
authors = ["Kerrick Long <me@kerricklong.com>"]
|
|
10
|
+
license = "AGPL-3.0-or-later"
|
|
11
|
+
publish = false
|
|
12
|
+
|
|
13
|
+
[lib]
|
|
14
|
+
crate-type = ["cdylib"]
|
|
15
|
+
|
|
16
|
+
[dependencies]
|
|
17
|
+
magnus = { git = "https://github.com/matsadler/magnus", branch = "main" }
|
|
18
|
+
tao = "0.34.5"
|
|
19
|
+
wry = "0.54.1"
|
|
20
|
+
ctrlc = "3.4"
|
|
21
|
+
|
|
22
|
+
[lints]
|
|
23
|
+
workspace = true
|