Skip to content

Conversation

@thatportugueseguy
Copy link
Contributor

Passage refactor to make it lib-first.

To accomplish the goal it was done

  • moving cli-specific modules to /bin
  • moving all other code to /lib
  • moved non-interactive commands to /lib too. Having the commands logic available to call from the lib has been requested before, so it was done too. This way we can use the same logic as in the CLI or create any custom logic as a lib user.
  • add interface files for all the files in /lib
  • updated config properties to be ref based, so it can be updated by the user of the lib, if there is no control over the env variables
  • added the option to call the commands with sudo invocation

Remarks

There are no changes in functionality. No changes have been done WRT side-effects (printing to stdout/stderr), i'll leave them to be done when we have more specific use-cases than the expected ones.

Check the usage examples below 👇

CRUD example using the commands
open Passage

let () =
let secret_name = Storage.Secret_name.inject "aa/aa" in
let create_secret secret_name ?comments text =
  Commands.Create.add ~comments secret_name text
in
(* #READ *)
let s =
  try
    print_endline "Getting secret";
  let s = Commands.Get.get_secret secret_name  in
  print_endline ("Got secret, val is: " ^ s);
  s
with Failure _ ->
(* #CREATE *)
    print_endline "Trouble getting the secret, creating secret";
    try
    let text = "\nhellow world\n\nsdf\nsdfsd\nsdfsdf\n" in
    create_secret secret_name ?comments:None text;
    print_endline "Created secret";
    text
    with Failure s -> Shell.die "%s" s
in
let () =
print_endline ("#GET: " ^ s ^ " ---- " ^ Commands.Get.get_secret secret_name) in
(* #UPDATE *)
let () = Commands.Replace.replace_secret secret_name "new_value" in
print_endline (
  "#REPLACE: " ^ Commands.Get.get_secret secret_name ^ " ---- " ^ Commands.Get.get_secret ~with_comments:true secret_name);
let () = Commands.Replace.replace_comment secret_name (fun _ -> "new_comments") in
print_endline (
  "#REPLACE COMMENT: " ^ Commands.Get.get_secret secret_name ^ " ---- " ^ Commands.Get.get_secret ~with_comments:true secret_name);
(* #DELETE *)
let () = Commands.Rm.rm_secrets ~verbose:false ~paths:[Storage.Secrets.to_path secret_name] ~force:true () in
print_endline "#RM: secret deleted";
try
let s = Commands.Get.get_secret secret_name  in
print_endline ("Got secret, val is: " ^ s);
with Failure _ ->
  print_endline "Secret not found as expected";

Output:

Getting secret                        
Trouble getting the secret, creating secret

I: using recipient group @root for secret aa/aa
I: using recipient jose.nogueira for secret aa/aa

If you are adding a new secret in a new folder, please keep recipients to a minimum and include the following:
- @root
- yourself
- people who help manage the secret, or people who would have access to it anyway
- people who need access to do their job
- servers/clusters that will consume the secret

If the secret is a staging secret, its only recipient should be @everyone.

Created secret
#GET: 
hellow world

sdf
sdfsd
sdfsdf
 ---- sdf
sdfsd
sdfsdf

#REPLACE: new_value
 ---- new_value

hellow world

#REPLACE COMMENT: new_value
 ---- new_value

new_comments

#RM: secret deleted
Secret not found as expected
using the lib functions directly
open Passage

let () =
let secret = {|-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLSEVxc1VJbGZzbVY5RW1Z
TzRRTGJJN213TVd2VThyVDlWVGNlUERjR2hrCmhrVG1vcnhpTXdUZFZTVEYyeTJs
ZmhzZkhZWnkxLzU0QnpWUHB1bTJPQkkKLS0tIEJFWGVtME9TOXVHTFdIOTdyckdI
VW1KUW96aVN1RDl1MXE4SG13YUs5T00KwFWW9DihtSwZ7HqmRMsmevv5UdkY+OQQ
DrO7UQurYV+ePA6WoI+I9z80zMQHAlA1isv6p+bOK4y+Z2oRy4By
-----END AGE ENCRYPTED FILE-----
|} in
 let decrypted = Age.decrypt_string ~identity_file:"/home/me/key.txt" ~silence_stderr:false secret in
 let () = match Secret.Validation.validate decrypted with
 | Ok Secret.Singleline -> print_endline "Secret is valid and single-line"
 | Ok Multiline -> print_endline "Secret is valid and multi-line"
 | Error (e, _) -> Shell.die "Secret is invalid: %s" e
in
let { Secret.text; comments; _ } = Secret.Validation.parse_exn decrypted in
 print_endline ("Decrypted secret: " ^ decrypted);
 print_endline ("Text: " ^ text);
 print_endline ("Comments: " ^ (Option.default "no comments" comments))

Output:

Secret is valid and single-line       
Decrypted secret: hello world

comment1
comment2

Text: hello world
Comments: comment1
comment2

* origin/master:
  update opam availability
  fix a couple of opam ci test issues
  v 0.2.0
  fix cmd description for new
@thatportugueseguy thatportugueseguy merged commit 6daf39a into master Dec 2, 2025
4 checks passed
@thatportugueseguy thatportugueseguy deleted the lib-refactor branch December 2, 2025 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants