From 8c890e759eb344d52a044d99681e52e22dc9d5f6 Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Mon, 15 Apr 2019 11:58:57 +0200 Subject: [PATCH] archives --- .gitignore | 1 + Cisco.org.gpg | Bin 18007 -> 15142 bytes Cisco.org.gpg_archive | 465 +++++++++++ HWP.org | 1230 +++++++++++++++++++++++++++- TODO.org | 14 +- agenda.org | 13 + cisco-epic-feature-flag-by-env.org | 72 ++ journal.org.gpg | Bin 6719 -> 6721 bytes refile.org | 4 + 9 files changed, 1755 insertions(+), 44 deletions(-) create mode 100644 agenda.org create mode 100644 cisco-epic-feature-flag-by-env.org create mode 100644 refile.org diff --git a/.gitignore b/.gitignore index 9912f513..2cde0486 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ ltximg HWP/ .*.icloud +.stack-work/ diff --git a/Cisco.org.gpg b/Cisco.org.gpg index 4da93194de5dd2c861dbe24df4c082eab36c3616..80535b166226485b2344f841b50a306556afd558 100644 GIT binary patch literal 15142 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 UqRm2Vm2YlazLY>snoseqwSu{@S^xk5 literal 18007 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 ei?cw*2EC8cgB4? + Adding Snehal, Craig, and Guillaume for awareness +> +> Hi Yann, +> +> Could you please provide an update on the issues 2440 and 2504 around not +> getting user emails? There are 1548 user ids from AMP customers with no email +> associated. +> +> Something seems to have changed, since recently we’ve been getting no emails for +> new users. This is essential for us to track adoption by product and set up +> targeted email campaigns. +> +> Thanks + + +* History API via Event Store :TOC_3_gh:QUOTE: + :PROPERTIES: + :ARCHIVE_TIME: 2019-04-04 Thu 16:29 + :ARCHIVE_FILE: ~/.deft/Cisco.org.gpg + :ARCHIVE_OLPATH: Epics + :ARCHIVE_CATEGORY: Cisco.org + :END: +#+BEGIN_QUOTE +- [[#oauth2-provider][OAuth2 Provider]] + - [[#workflow][Workflow]] + - [[#authorize][=/authorize=]] + - [[#approve][=/approve=]] + - [[#refuse][=/refuse=]] + - [[#token][=/token=]] + - [[#oauth2-in-iroh-auth-spec-rfc-second-pass][OAuth2 in IROH-Auth Spec RFC second pass]] + - [[#vocabulary][Vocabulary]] + - [[#client-registration][Client Registration]] + - [[#protocol-endpoints][Protocol Endpoints]] + - [[#obtaining-authorization][Obtaining Authorization]] + - [[#oauth2-provider-epic][OAuth2 Provider Epic]] + - [[#functional-spec][Functional Spec]] + - [[#tasks][Tasks]] + - [[#technical-spec][Technical Spec]] + - [[#oauth2-epics-3rd-pass][OAuth2 Epics (3rd pass)]] + - [[#spa-compatible-oauth2][SPA compatible OAuth2]] + - [[#users-made-oauth2-clients][User's made OAuth2 clients]] + - [[#internal-user-representation][Internal User Representation]] + - [[#oauth2-client-credentials-grant][OAuth2 Client Credentials Grant]] + - [[#iroh-admin-dashboard][IROH Admin Dashboard]] + - [[#oauth2-enhancements][OAuth2 Enhancements]] +- [[#scopes-dictionary][Scopes Dictionary]] +- [[#document-for-raghavaiah][Document for Raghavaiah]] + - [[#franks-proposal-auth-config-untangling][Frank's proposal; Auth config untangling]] + - [[#int][INT]] + - [[#test][TEST]] + - [[#proposal][Proposal]] + - [[#int-1][INT]] + - [[#prod-nam][PROD NAM]] + - [[#prod-eu][PROD EU]] + - [[#prod-apjc][PROD APJC]] + - [[#test-1][TEST]] +- [[#daily-standup-meeting][Daily Standup Meeting]] + - [[#2019-02-27-wed][<2019-02-27 Wed>]] + - [[#release-119][release 1.19]] + - [[#individual-updates][individual updates]] + - [[#uiux][UI/UX]] + - [[#misc][Misc]] + - [[#2019-02-25-mon][<2019-02-25 Mon>]] + - [[#2019-01-18-fri][<2019-01-18 Fri>]] + - [[#individual-update][Individual update]] + - [[#2019-01-23-wed][<2019-01-23 Wed>]] + - [[#ops][ops]] + - [[#rel-116][rel 1.16]] + - [[#individual-update-1][Individual update]] + - [[#ux-design-update][UX Design update]] + - [[#design-update][Design update]] + - [[#2019-01-11-fri][<2019-01-11 Fri>]] + - [[#ops-weather-report][Ops Weather Report]] + - [[#individual-reports][Individual Reports]] + - [[#design][Design]] + - [[#2019-01-09-wed][<2019-01-09 Wed>]] + - [[#ops-1][Ops]] + - [[#reports][Reports]] + - [[#2019-01-08-tue][<2019-01-08 Tue>]] + - [[#ops-2][OPS]] + - [[#release-status][Release Status]] + - [[#angela][Angela]] + - [[#2019-01-04-fri][<2019-01-04 Fri>]] + - [[#2018-12-07-fri][<2018-12-07 Fri>]] + - [[#topics][Topics]] + - [[#ops-3][Ops]] + - [[#rel][Rel]] + - [[#2018-11-28-wed][<2018-11-28 Wed>]] + - [[#release-114][release 1.14]] + - [[#ops-report][Ops report]] + - [[#individual-report][Individual Report]] + - [[#ux-design-report][UX Design Report]] + - [[#2018-11-26-mon][<2018-11-26 Mon>]] + - [[#2019-01-11-fri-1][<2019-01-11 Fri>]] + - [[#2018-11-19-mon][<2018-11-19 Mon>]] + - [[#ops-4][Ops]] + - [[#ui][UI]] + - [[#individual-reports-1][Individual reports]] + - [[#jwt-lifetime][JWT lifetime]] + - [[#2018-10-31-wed][<2018-10-31 Wed>]] + - [[#individual-reports-2][Individual Reports]] + - [[#2018-10-22-mon][<2018-10-22 Mon>]] + - [[#individual-updates-1][Individual Updates]] + - [[#2018-10-10-wed][<2018-10-10 Wed>]] + - [[#2018-10-01-mon][<2018-10-01 Mon>]] + - [[#2018-09-19-wed][<2018-09-19 Wed>]] + - [[#ops-weather-reports][Ops weather reports]] + - [[#release-report][Release report]] + - [[#doc-report][Doc report]] + - [[#personal-report][Personal report]] + - [[#ux-update][UX Update]] + - [[#pto][PTO]] + - [[#2018-09-18-tue][<2018-09-18 Tue>]] + - [[#2018-09-11-tue-secretary-nola][<2018-09-11 Tue> Secretary: Nola]] + - [[#topics-1][Topics]] + - [[#pr-merge][PR merge]] + - [[#pto-1][PTO]] + - [[#2018-09-10-mon][<2018-09-10 Mon>]] + - [[#yann][Yann]] + - [[#ux-design][UX Design]] + - [[#idp-issue][IdP Issue]] + - [[#2018-08-14-tue][<2018-08-14 Tue>]] + - [[#2018-08-17-fri][<2018-08-17 Fri>]] + - [[#topics-2][Topics]] + - [[#ops-report-1][Ops report]] + - [[#individual-reports-3][Individual Reports]] + - [[#ux-design-update-1][UX Design Update]] + - [[#pto-2][PTO]] + - [[#2018-08-13-mon-secretary-paula][<2018-08-13 Mon> Secretary Paula]] + - [[#individual-report-1][Individual report]] + - [[#2018-08-08-wed-secretary-john][<2018-08-08 Wed> Secretary John]] + - [[#individual-report-2][Individual Report]] + - [[#2018-08-07-tue][<2018-08-07 Tue>]] + - [[#brian][Brian]] + - [[#2018-08-06-mon][<2018-08-06 Mon>]] + - [[#bart-resigned-by-mail][Bart resigned (by mail)]] + - [[#individual-report-3][Individual report]] + - [[#2018-08-03-fri][<2018-08-03 Fri>]] + - [[#topic][Topic]] + - [[#individual-update-2][Individual Update]] + - [[#ops-report-2][Ops Report]] + - [[#release-status-1][Release Status]] + - [[#2018-08-01-wed][<2018-08-01 Wed>]] + - [[#topics-3][Topics]] + - [[#update-from-craig][Update from Craig]] + - [[#individual-reports-4][Individual Reports]] + - [[#blocking-bug-622][Blocking Bug #622]] + - [[#ops-5][Ops]] + - [[#pto-3][PTO]] + - [[#2018-07-25-wed-secretary-matt][<2018-07-25 Wed> Secretary Matt]] + - [[#individual-reports-5][Individual Reports]] + - [[#2018-07-24-tue][<2018-07-24 Tue>]] + - [[#release][Release]] + - [[#operation-report][Operation Report]] + - [[#release-notes][Release Notes]] + - [[#2018-07-23-mon-secretary-alex][<2018-07-23 Mon> Secretary Alex]] + - [[#individual-reports-6][Individual Reports]] + - [[#2018-07-17-tue][<2018-07-17 Tue>]] + - [[#topics-4][Topics]] + - [[#2018-07-16-mon][<2018-07-16 Mon>]] + - [[#topics-5][Topics]] + - [[#individual-reports-7][Individual Reports]] + - [[#2018-07-13-fri][<2018-07-13 Fri>]] + - [[#2018-07-11-wed-secretary-bart][<2018-07-11 Wed> Secretary: Bart]] + - [[#individual-update-3][Individual update]] + - [[#release-deployment-day][Release Deployment Day]] + - [[#conversation-in-the-iroh-channel][conversation in the IROH channel]] + - [[#soliciting-topic][soliciting topic]] + - [[#impersonate-api][impersonate API]] + - [[#integrating-with-amp-test-env][integrating with AMP test env]] + - [[#update-from-john][update from John]] + - [[#2018-07-09-mon][<2018-07-09 Mon>]] + - [[#release-1][Release]] + - [[#pto-4][PTO]] + - [[#][...]] + - [[#2018-07-06-fri-secretary-jesse][<2018-07-06 Fri> Secretary Jesse]] + - [[#release-2][Release]] + - [[#discovery][Discovery]] + - [[#bart-demo][Bart Demo]] + - [[#upcoming-pto][Upcoming PTO]] + - [[#2018-07-04-wed][<2018-07-04 Wed>]] + - [[#2018-07-03-tue][<2018-07-03 Tue>]] + - [[#2018-06-29-fri][<2018-06-29 Fri>]] + - [[#iroh-ui][IROH UI]] + - [[#pto-5][PTO]] + - [[#2018-06-22-fri-secretary-yann][<2018-06-22 Fri> Secretary Yann]] + - [[#release-status-2][Release Status]] + - [[#ops-report-3][Ops Report]] + - [[#ttp-headnodes][TTP Headnodes]] + - [[#pto-update][PTO update]] + - [[#question-about-possible-users-information-leaks-in-the-kibana-logs][Question about possible user's information leaks in the kibana logs]] + - [[#2018-06-15-fri][<2018-06-15 Fri>]] + - [[#2018-06-01-fri][<2018-06-01 Fri>]] + - [[#ops-status-aws-outage][OPS status (AWS outage)]] + - [[#ui-status-update][UI Status update]] + - [[#naga-status-update][Naga Status Update]] + - [[#certifcate-expiration][Certifcate expiration]] + - [[#kibana-dashboard][Kibana dashboard.]] + - [[#pto-6][PTO]] + - [[#2018-05-30-wed-secretary-bart][<2018-05-30 Wed> Secretary: Bart]] + - [[#2018-05-23-wed][<2018-05-23 Wed>]] + - [[#2018-05-14-mon-secretary-jesse][<2018-05-14 Mon> Secretary: Jesse]] + - [[#2018-04-24-tue-secretary-chris][<2018-04-24 Tue> Secretary: Chris]] + - [[#2018-04-23-mon-secretary-jesse][<2018-04-23 Mon> Secretary: Jesse]] + - [[#2018-04-11-wed][<2018-04-11 Wed>]] + - [[#2018-03-27-tue-secretary-daniel][<2018-03-27 Tue> Secretary: Daniel]] + - [[#release-3][release]] + - [[#2018-03-14-wed-secretary-daniel][<2018-03-14 Wed> Secretary: Daniel]] + - [[#2018-03-02-fri-secretary-craig][<2018-03-02 Fri> Secretary: Craig]] + - [[#2018-02-28-wed-secretary-yann][<2018-02-28 Wed> Secretary: Yann]] + - [[#saml-vulnerability][SAML Vulnerability]] + - [[#blocked-on-es-maximum-nb-of-field-error][Blocked on ES maximum nb of field error]] + - [[#blocked][Blocked]] + - [[#some-dev-start-to-become-painful][Some dev start to become painful]] + - [[#release-status-3][Release status]] + - [[#cisco-anyconnect-problem][Cisco AnyConnect Problem]] + - [[#2018-02-27-tue-secretary-paula][<2018-02-27 Tue> Secretary: Paula]] + - [[#report-from-berlin][Report from Berlin]] + - [[#int--test][Int / Test]] + - [[#2018-02-26-mon-secretary-alex][<2018-02-26 Mon> Secretary: Alex]] + - [[#tg-login][TG Login]] + - [[#tenzin-conf][Tenzin Conf]] + - [[#offsite][Offsite]] + - [[#2018-02-23-fri][<2018-02-23 Fri>]] + - [[#2018-02-19-mon-secretary-jesse][<2018-02-19 Mon> Secretary: Jesse]] + - [[#2018-02-07-wed-secretary-yann][<2018-02-07 Wed> Secretary: Yann]] + - [[#wait_for-for-refresh-in-es-impact][wait_for for refresh in ES impact]] + - [[#chris-stuck-too-long-on-1225][Chris: stuck too long on #1225]] + - [[#release-status-4][Release status]] + - [[#2018-02-05-mon-secretary-chris][<2018-02-05 Mon> Secretary: Chris]] + - [[#2018-02-01-thu-secretary-alex][<2018-02-01 Thu> Secretary: Alex]] + - [[#2018-01-31-wed-secretary-matt][<2018-01-31 Wed> Secretary: Matt]] + - [[#spectre-patches][Spectre patches]] + - [[#ctia-investigate-issue][CTIA Investigate Issue]] + - [[#html-route][HTML route]] + - [[#2018-01-30-tue-secretary-brian][<2018-01-30 Tue> Secretary: Brian]] + - [[#scratchpad-service-guillaume][Scratchpad Service (Guillaume)]] + - [[#error-reporting-in-iroh-ui-interface-jesse][Error Reporting in IROH UI Interface (Jesse)]] + - [[#amp-visibility-design-recap][AMP Visibility design recap]] + - [[#amp-visibility-builds][AMP Visibility Builds]] + - [[#2018-01-29-mon-secretary-houman][<2018-01-29 Mon> Secretary: Houman]] + - [[#status-of-the-release][Status of The release]] + - [[#investigation--snapshots--incident--scratchpads][Investigation & Snapshots / Incident & Scratchpads]] + - [[#ui-rewrite][UI rewrite?]] + - [[#2018-01-25-thu-secretary][<2018-01-25 Thu> Secretary:]] + - [[#2018-01-24-wed-secretary-paula][<2018-01-24 Wed> Secretary: Paula]] + - [[#timeout-issue][Timeout issue]] + - [[#client-lib-visibility-lib][Client Lib, Visibility Lib]] + - [[#deadline][Deadline]] + - [[#metrics-we-need-in-production][Metrics we need in production]] + - [[#2018-01-22-mon-secretary-guillaume][<2018-01-22 Mon> Secretary: Guillaume]] + - [[#contact-to-tg-integration][Contact to TG Integration]] + - [[#amp-global-intel-next-step][AMP Global Intel Next Step]] + - [[#iroh-ui-1][IROH-UI]] + - [[#2018-01-18-thu-secretary-jesse][<2018-01-18 Thu> Secretary: Jesse]] + - [[#2018-01-17-wed-secretary-alex][<2018-01-17 Wed> Secretary: Alex]] + - [[#2018-01-16-tue-secretary-yann][<2018-01-16 Tue> Secretary: Yann]] + - [[#prod-patching-meltdown][Prod Patching Meltdown]] + - [[#tg-indicator][TG indicator]] + - [[#2018-01-11-thu-secretary-chris][<2018-01-11 Thu> Secretary: Chris]] + - [[#story-boards][Story boards]] + - [[#2018-01-10-wed-secretary-sam][<2018-01-10 Wed> Secretary: Sam]] + - [[#status-update][status update]] + - [[#2018-01-09-tue][<2018-01-09 Tue>]] + - [[#offsite-1][offsite]] + - [[#yesterday-meeting][yesterday meeting]] + - [[#update-ui-stuff][update UI stuff]] + - [[#job-description][Job description]] + - [[#2018-01-08-mon][<2018-01-08 Mon>]] + - [[#2018-01-05-fri][<2018-01-05 Fri>]] + - [[#secretary-alex][Secretary @Alex]] + - [[#ui-breakout][UI breakout]] + - [[#project-boards][Project Board(s)]] + - [[#offsite-2][Offsite]] + - [[#new-position][New position]] + - [[#2018-01-04-thu][<2018-01-04 Thu>]] + - [[#2018-01-03-wed][<2018-01-03 Wed>]] + - [[#2018-01-02-tue][<2018-01-02 Tue>]] + - [[#craig][Craig]] + - [[#2017-12-04][<2017-12-04>]] + - [[#2017-11-29][<2017-11-29>]] + - [[#2017-11-28][<2017-11-28>]] + - [[#2017-10-27][<2017-10-27>]] + - [[#2017-10-26][<2017-10-26>]] + - [[#2017-10-18---nil][<2017-10-18> - nil]] + - [[#2017-10-17---nil][<2017-10-17> - nil]] + - [[#2017-10-16][<2017-10-16>]] + - [[#2017-09-26][<2017-09-26>]] +- [[#tech-notes][Tech notes]] + - [[#ops-connect-to-int][OPS Connect to Int]] +- [[#email-of-users][Email of users]] + - [[#channel-email][channel: email]] + - [[#introduction][Introduction]] + - [[#plan][Plan]] + - [[#part-1][Part 1]] + - [[#part-2][Part 2]] + - [[#technical-details][Technical Details]] +#+END_QUOTE + +** Introduction + + Multiple recent features/changes would be improved by a system to keep + track of history events (see #2370, #2425, #2426). + + - keep track of login dates (right now, we only keep track of the + latest 5 login dates, we also can't keep much meta infos about those + logins like IP addresses, HTTP referrers, etc...) + - Administrative tasks, a new notion of role will give some user the + right to manage resources like other users / other OAuth2 clients. + As such we should keep track of who is doing what and when to + prevent subtle attack and/or errors. + + For now, all these information can be gathered through our internal logging + system. I think this should become an internal API. Typically our customer will + want to know who is the admin that blocked some user and when. + +** Plan + +*** Part 1 + + Keep track of: + + - user logins + - user profile updates + - client updates (who modified the client and when) + + I think we should start with a very small plan first. We could take + advantage of the current events we are sending to Riemann and put those + events (or only part of them) in a searchable store. The advantage is + that we already have a service with a clear and simple API and is used + in many different other services. + + We should then impose stronger constraints to the event format. It + should be beneficial for both internal API and analysis via Kibana (the + team responsible to analyse user behaviour expressed difficulties in + dealing with the lack of common format and missing infos for some + events). + + This approach will also make it easier to simplify the internal + structure of the client object and be able to remove details about the + internal workflow in that object (and also others). Typically, it should + remove the need for many metadatas of the object (updated-by, + approval-status, etc...) + + During this first step the events should correspond to *things that + happened* and as such should be named in past tense (*User Blocked*, + *Client Deleted*, etc...). + +*** Part 2 + +/remark/: Part 2 is out of the scope of this issue and should be its own issue +later. + + I think we should think about not only using "Events" (things that + happened in the past) but also /Commands/ (requests for things to + happen, named with verb in imperative mood). And from there we might + start to create /Aggregates/ (read-only views constructed from events). + Using this architecture, a single events would be able to be used to + provide different views (historical views about a single client, list of + users that modified clients in the past, stats about users, etc...) + +** Technical Details + +- create an Event Store that can also be a CRUDStore to be searchable. I think + it should be backed by PostgreSQL to ease views when we might need to make + joins. +- the =Event= schema should contain an =event-type= this should always be named in + the past tense. (note this structure provide a quite good template for events + structure that could ease the search in kibana in the future) + #+BEGIN_SRC clojure + (s/defschema Event + {:event-type s/Keyword ;; prefer namespaced keywords that should link to a schema + :event-params {s/Any s/Any} ;; some printable hash-map that match the schema linked by event-type + :emiter + (st/optional-keys + {:service s/Keyword ;; should be an service-name + :user-id s/Str ;; should be the user-id of the person responsible for the event + :client-id s/Str ;; if the operation is done via a client provide the client-id + :impersonated-by s/Str ;; if impersonated should provide the user-id of the master user + :user User ;; all gory details about the User + :org Org ;; all gory details about the org + })}) + #+END_SRC + +- update the riemann-reporter service to be able to write to multiple stores and + with the ability to filter on set of event-types. So we could create stores + that could contains only some event-types. Also provide a list of event fields to track. + As riemann event-store will want all the details about an event while event in a searchable + store should not. +- provide another =send-event= method for the =riemann-reporter= service to be able to send + event with all the mandatory infos, take care of removing all user / org infos from the event destined + #+BEGIN_SRC clojure + (s/defn send-event [event-type event-params emiter-infos] :- Event ...) + #+END_SRC +- update the =send-event= call to match the correct format and configure one + searchable store of riemann reporter store to track those events. +- update the =/login= handler not to put login dates infos in the user object. +- update the =/profile= endpoint to use thoses events to display latests login dates. + diff --git a/HWP.org b/HWP.org index 739df5ed..81cdc787 100644 --- a/HWP.org +++ b/HWP.org @@ -1,46 +1,1202 @@ -#+TODO: TODO TO-CLEAN TO-REVIEW | DONE +# Created 2019-04-01 Mon 13:31 #+TITLE: Haskell for the working programmer #+AUTHOR: Yann Esposito -#+EMAIL: yann.esposito@gmail.com +#+TODO: TODO TO-CLEAN TO-REVIEW | DONE #+LANGUAGE: en #+KEYWORDS: haskell #+PROPERTY: header-args :output-dir HWP :mkdirp yes :tangle-mode (identity #o755) +* TO-CLEAN Introduction + +This is somehow a follow-up from Learn Haskell Fast and Hard. +Which was more about being able to /play/ with Haskell than to /work/ with it. + +This is also an experiment. +I'm not sure if it will be as positive as I hope. +This book try to be a good resource to learn Haskell but to speed up the +learning in the first part I'll skip the explanation about why Haskell does +things the way it does. +As a consequence if you don't keep in mind that there is *very good* reasons to +make some things way more difficult in Haskell than in other languages you +might miss the real reason. + +Also don't forget in the beginning you might only see what is more difficult or +harder to achieve in Haskell. +But for each thing harder, keep in mind that there are very difficult things in +other languages that are solved extremely easily in Haskell. +And I personnally believe the things Haskell make easier are essential to reach +the best balance between speed, elegance, safety and pragmatism with regards to +any programming language I ever used before. + +So this book might be a bit raw. +And in fact not really "fun" unfortunately. +But it should be efficient. + +This book is aimed to be one of the fastest way to learn how to be productive +with Haskell. + +Know that there still will be a very long road ahead once this book will be +finished to master Haskell. That should be ok. Even with those basic knowledge, +you should already be more productive in Haskell than in most other programming. + +Modern computing has unfortunately less to do with algorithmic than to create a +mashup of libs and external APIs. +So while learning all the details of Haskell can seems like an impossible challenge. +Learning the necessary skills to be productive shouldn't be that hard. + +What does this book will talk about. + +1. Having a clean and stable dev environment +2. Basic Introduction to the language +3. Professional Project developement workflow +4. Make command line program +5. Use external libraries +6. Handle the filesystem +7. Handle a few DBs +8. Make a basic REST API + +What Haskell can do few other programming language can. + +Ability to put strong constraingt on part of the code. For exemple you can have +confidence in 3rd party functions. You can be certain that there will be NO side +effect. Or you can also ensure that part of you code can only write logs and not +access the DB. We'll technique that will ensure that subpart of the code will +only access the User table in your DB etc... + +Writting parallel and concurrent code because /very/ easy to write. +While this is generally a nightmare in most programming language. + +** TO-CLEAN What does "working programmer" stand for? + +Being able to: + +- create a new working program from scratch, +- work with the filesystem (read/write files/directories), +- work with BDD (SQLite, PostgresSQL, MongoDB, etc...), +- work with network (send/receive HTTP request), +- make a REST API, +- use most libraries (OpenGL, ncurses, etc...) +- write test for your application, +- to deploy your application + +This is more about being an user, consumer from the Haskell community than being +an active contributor. Hopefully the gap won't be hard to pass from user to +contributor. So I'll write a minimal chapter about how to write your own library +and publish it for other developpers. + +** TO-CLEAN Prerequiste + +The target audience I'm writting this book for is software developpers. + +You should: + +- be familiar with some programming language, +- be familiar with command line in a shell, +- know how to editing text files (I try to focus on generic editors like emacs, + vim, etc...), +- know the basic usage of =git= + +If you don't know that, your journey with this book might be a bit difficult but +I'll do my best to not make it impossible. + +** TO-CLEAN Opinionated + +Keep in mind that Haskell has a very active and open ecosystem. +And the language itself let you make very different choices to the fundamentals. + +This book is very opinionated, because I wanted to be efficient in learning +fast for some specific kind of personalities. + +It might not be for you. +One of my goal is to shortcircuit some classic learning detour. + +For a lot of decisions I generally make only one choice. I'll try to talk about +the other choices and it will be your duty to explore other choices after you +completed this book to decide which is the one that has your preference. + +Also note that this book was written in the past. And as I said Haskell +ecosystem evolve very fast. And some choices which are an evidence today might +be deprecated in a few months from now. + +Typically there are many different and concurrent web frameworks, db libs, etc.. + +** TO-CLEAN A Word about Haskell philosophy + +One Haskell main characteristic is that it tends to make the right/most secure +choice by default. + +A very simple example is that it is generally harder to write unsafe code than +to write safe and pure code. + +Also one of the reason I think Haskell is percieved as hard to learn by many +people is that you generally need to ingest a lot of concepts before being able +to be productive. +#+TODO: TODO TO-CLEAN TO-REVIEW | DONE +#+LANGUAGE: en +#+KEYWORDS: haskell +#+PROPERTY: header-args :output-dir HWP :mkdirp yes :tangle-mode (identity #o755) + +** TO-CLEAN Install a dev environment (about 30 minutes) + + Installing a dev environment should hopefully be the most boring part of this + book. But this is a necessary price to pay to really get why Haskell is + considered so great by people using it. + +**** TO-CLEAN Working environment + + A thing to note is the distinction between learning a language for personal + interrest for some personal project and learning with the goal to achieve a + "product" with some hard deadline. + + So for example, it can be nice to understand the language by playing inside a + REPL. We won't use that much in this book as the goal is not to really gain a + deeper knowledge but perhaps to be able to /use/ the language. + + The problem I try to solve in this book is to make you a professional /user/ of + Haskell more than a /contributor/ to Haskell. While I encourage everybody to + gain deeper understanding on the internals of Haskell this is not the primary + goal of this book. + + What I mean by professional /user/ is that you should have the following + features at your disposal: + + - DCVS + - Generated documentation + - Tests (Unit tests, Generative tests, Integration tests, etc...) + - Benchmark + - Continuous Integration + - Continuous Deployment + + Choices: + + - Raw: get GHC and cabal exectuable and work with that. Too long and manual + - Nix: this is really great because it's like a super make that can deal with + external dependencies. Certainly the best tool in the long term. + - Stack: fast to install focused on being user friendly. Has a lot of easy to + use features like: + - integration with docker that will make it easy to cross-compile, deploy. + - integration with nix + - easy to deal with many private repositories + - good professional starting templates + +**** TO-CLEAN Stack + + I recommend [[https://haskellstack.org][stack]]. But there are many different method to install Haskell. + Stack should be simple and straight to the point. + + If thing haven't changed since the book was written it could be installed with: + + #+BEGIN_SRC shell + curl -sSL https://get.haskellstack.org/ | sh + #+END_SRC + +**** TO-CLEAN git + + You should have =[[https://git-scm.com][git]]= installed. + +**** TO-CLEAN Editor + + You should check any of the supported editor here: + + https://github.com/rainbyte/haskell-ide-chart#the-chart-with-a-link-to-each-plug-in + + I personnaly use [[http://spacemacs.org][spacemacs]] with the haskell layer because it comes with battery + included. If you're not used to vim keybindings I believe it is easy to switch + to more classical editor keybindings easily. + + Even if I don't have a strong opinion on the editor you should choose. It should + at least be easy to support the Haskell tooling, like intero or ghc-mod. Because + it's one of the best part of Haskell. + + For example without any configuration I have the following features: + + - I see errors, warn and even code hints while I'm typing my code. + - very good code completion + - auto styling of my source code and be able to change the style of my entire + buffer + - be able to get the type of the expression under my cursor + - be able to add the type of a top level declaration + - be able to launch a repl easily loading the current code of the file I'm + currently editing + + And many other nice features. + + Note that in the past I had some problem with ghc-mod during upgrades while + intero was mostly a no problem story. + + It is also useful to have hoogle and hayoo, which are search engine focused on + Haskell. + +***** TO-CLEAN Spacemacs + + So if you want to choose spacemacs: + + 1. Install a recent emacs + 2. =git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d= + 3. Launch emacs + 4. Edit your =~/.spacemacs= file to add to the layer list: + + #+BEGIN_SRC elisp + haskell + (auto-completion :variables + auto-completion-enable-help-tooltip t + auto-completion-enable-short-usage t) + #+END_SRC + + If you're not used to vim keybinding and it is too much to handle for you. + I think you can change the value of =dotspacemacs-editing-style= from ='vim= + to ='hybrid= or ='emacs= in the =.spacemacs= file. + + It should be good now. +**** TO-CLEAN Conclusion + + First you can congratulate yourself to have installed all the prerequiste to + have a great working development environment. + + I know it was already a lot of boring tasks to perform before being able to + write any line of code. But I promise it will be worth it. + + By starting with this template, you won't use the classic prelude. It's quite a + strong opinionated move. Because many classic function will be overwritten by + safer/more generic one. + + So be prepared that the actual learning route is jumping other classical + learning steps you can find in other learning resources. Don't worry I'll do my + best to make the jump as natural as possible. + #+TODO: TODO TO-CLEAN TO-REVIEW | DONE + #+LANGUAGE: en + #+KEYWORDS: haskell + #+PROPERTY: header-args :output-dir HWP :mkdirp yes :tangle-mode (identity #o755) + +* TODO Data Management + +You can think of Haskell and its Prelude as a Linux installation. +You have a kernel and a bunch of executable. + +So in order to manage your Unix env you need to know a few command line first. +Then, slowly with the need and experience, you'll learn more and more commands. + +So we'll do the same thing here. +We'll start with only what we need to start a project. +And You'll be introduced with new notion as they are needed. + +** Prelude/Protolude + +So Haskell prelude is old and it is very easy to use more modern prelude. +So I'll tend to do just that. + +*** Data Manipulation Functions +* TODO Effect Management + +In that part of the book, we'll use simple examples. Thus instead of going +directly to a full project structure we'll focus on the language. That file can +be treated as a single executable strict. + +For example: + +#+BEGIN_SRC haskell +#!/usr/bin/env stack +{- stack script + --resolver lts-13.13 + --install-ghc + --package protolude +-} +{-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE OverloadedStrings #-} +import Protolude + +main = putText "Hello World!" +#+END_SRC + +The firsts line are simply here to set the correct execution environment. +The real program starts after them. +Once =stack= will be installed (see the /Install a dev environment/ section) +if you put that content in a file named =hello.hs= then you can launch it with: + +#+BEGIN_SRC +> chmod +x hello.hs +> ./hello.hs +#+END_SRC + +The first time it is launched can take a little bit of time because it will +download all dependencies. The advantage of this form of distribution is that it +is a quasi self-contained exectuable. That's a good one for minimal examples. + +But after a short introduction we'll use full projects. + +We'll start by example first and all notion will be introduced as they appear. +If you find confident you could feel free to skip some descriptions and +explanations. + +** TODO Short Examples / Scripts +*** TO-CLEAN Guess a number +**** TO-CLEAN Print and read things + +Now let's modify the code of =main= to print things. +First comment the import line for =Lib=. +Haskell comment are =--= till the end of the line or ={- .... -}= +for multiline comments. +Without this comment you'll get a warning that this import is unused. +And by default we compile using =-Werror= flag to GHC which tell that the +compilation should fail also on warnings as well as on errors. + +The default template tend to be a professional environment and has more +restrictions in order to maximize confidence in quality. + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + import Protolude + + main = putText "Hello, world!" +#+END_SRC + +Simple and natural. +Now let's ask your name. + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + import Protolude + + main = do + putText "What is your name?" + name <- getLine + putText ("Hello " <> name <> "!") +#+END_SRC + +We can try that in the REPL (GHCI). You should be able to start it from your +editor. For example in spacemacs I can load the current buffer (open file) in +the REPL with =SPC m s b=. + +You could also start the repl in a terminal with =stack ghci= +And then load the module with =:l hello_name.hs=. +The =:l= is a shortcut for =:load=. + +#+BEGIN_SRC + > stack ghci + + Warning: No local targets specified, so ghci will not use any options from your package.yaml / *.cabal files. + + Potential ways to resolve this: + ,* If you want to use the package.yaml / *.cabal package in the current directory, use stack init to create a new stack.yaml. + ,* Add to the 'packages' field of ~/.stack/global-project/stack.yaml + + Configuring GHCi with the following packages: + GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help + Loaded GHCi configuration from /private/var/folders/bp/_8thkcjd4k3g81mpxtkq44h80000gn/T/ghci70782/ghci-script + Prelude> :l hello_name.hs + [1 of 1] Compiling Main ( hello_name.hs, interpreted ) [flags changed] + Ok, one module loaded. + ,*Main> main + What is your name? + Yann + Hello Yann! +#+END_SRC + +But you should also simply run it from command line: + +#+BEGIN_SRC + > ./hello_name.sh + What is your name? + Yann + Hello Yann! +#+END_SRC + +OK simple enough. + +But let's take a moment to understand a bit more what's going on. + +We started with the =do= keyword. +It's a syntactical sugar that helps in combining multiple lines easily. +Let's take a look at the type of each part. + +#+BEGIN_SRC haskell + putText :: Text -> IO () +#+END_SRC + +It means that =putText= is a function that take a =Text= as parameter and return +an =IO ()=. +Mainly =IO ()= simply means, it will return =()= (nothing) while doing some IO +or border effect. +The border effect here being, writing the text to the standard output. + +#+BEGIN_SRC haskell + putText "What is your name?" :: IO () +#+END_SRC + +So yes this line make an IO but returns nothing significant. + +#+BEGIN_SRC haskell + name <- getLine +#+END_SRC + +The function =getLine= will read from standard input and provide the line read +and send the value as a =Text=. If you look at the type of =getLine= you have: + +#+BEGIN_SRC haskell + getLine :: IO Text +#+END_SRC + +And that means that to be able to retrieve and manipulate the Text returned by +in an "IO context" you can use the =<-= notation. +So in the code the type of =name= is =Text= + +More generally if =foo :: IO a= then when you write + +#+BEGIN_SRC haskell + do + x <- foo :: IO a +#+END_SRC + +Then the type of =x= is =a=. + +Finally the last line: + +#+BEGIN_SRC haskell + putText ("Hello " <> name <> "!") +#+END_SRC + +=putText= take a =Text= as argument so: =("Hello " <> name <> "!") :: Text=. + +So =(<>)= is the infix operator equivalent to the function =mappend=. +Here are equivalent way to write the same thing: + +#+BEGIN_SRC haskell + "Hello" <> name <> "!" + "Hello" `mappend` name `mappend` "!" + + mappend "Hello" (mappend name "!") + (<>) "Hello" ((<>) name "!") +#+END_SRC + +So in Haskell if your function contains chars it will be a prefix function. +If your function contains special chars then it is considered to be an infix +operator. + +You can use your function as infix if you put "`" around it name. +And you can make your operator prefix if you put it inside parentheses. + +So you should have remarqued a pattern here. +Which is really important. Each line of a =do= bloc has a type of =IO a=. + +#+BEGIN_SRC haskell + main = do + putText "What is your name?" :: IO () + name <- getLine :: IO Text + putText ("Hello " <> name <> "!") :: IO () +#+END_SRC + +So whenever you have an error message try to think about the type of your +expression. + +Another very important aspect to notice. +The type of ="Hello " <> name <> "!"= is =Text= not =IO Text=. +This is because this expression can be evaluated purely. +Without any side effect. + +Here we see a clear distinction between a pure part of our code and the impure +part. + +#+BEGIN_QUOTE + + +*☞ Pure vs Impure* (function vs procedure) + +That is one of the major difference between Haskell and other languages. +Haskell provide a list of function that are considered to have border effects. +Those functions are given a type of the form =IO a=. + +And the type system will restrict the way you can manipulate function with type +=IO a=. + +So, first thing that might be counter intuitive. +If an expression has a type of =IO a= it means that we potentially perform a +side effect and we "return" something of type =a=. + +And we don't want to ever perform a side effect while doing any pure evaluation. +This is why you can't write something like: + +#+BEGIN_SRC haskell + -- DOESN'T COMPILE + main = do + putText ("Hello " <> getLine <> "!") +#+END_SRC + +Because you need to "traverse" the =IO= barrier to get back the value after the +evaluation. +This is why you NEED to use the =<-= notation. +Now knowing if a code is potentially making any side effect is /explicit/. +#+END_QUOTE + +***** TO-CLEAN Strings in Haskell digression + +Generally working with string is something you do at the beginning of learning a +programming language. +It is straightforward. +In Haskell you have many different choices when dealing with Strings depending +on the context. +But let just say that 95% of the time, you'll want to use Strict =Text=. + +Here are all the possible choices: + +- =String=: Just a list of =Char= very inefficient representation, +- =Text=: UTF-16 strings can be Lazy or Strict, +- =Bytestring=: Raw stream of =Char= and also =Lazy.Bytestring=. + +That is already 5 different choices. But there is another package that provide other string choices. +In =Foundation= the strings are =UTF-8=. + +Hmmm... so much choices. + +A rule of thumbs is to never use =String= for anything serious. +Use =Text= most of the time because they support encoding. +Use =Bytestring= if you need efficient bytes arrays. + +By using Protolude, we naturally don't use =String=. + +**** TO-CLEAN Guess my age program + +So far so good. +But the logic part of the code should be in a library in =src/= directory. +Because this part is easier to test. + +The =src-exe/Main.hs= should be very minimalist, so now let's change its content +by: + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + import Protolude + + guess :: IO () + guess = undefined + + main :: IO () + main = do + guess + putText "Thanks for playing!" +#+END_SRC + +We know that the type of guess must be =IO ()=. +We don't know yet what the code will be so I just used =undefined=. +This way the program will be able to typecheck. + +The next step is to define the ~guess~ function. + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + import Protolude + + guess :: IO () + guess = guessBetween 0 120 + + guessBetween :: Integer -> Integer -> IO () + guessBetween minAge maxAge = do + let age = (maxAge + minAge) `div` 2 + if minAge == maxAge + then putText ("You are " <> show minAge) + else do + putText ("Are you younger than " <> show age <> "?") + answer <- getLine + case answer of + "y" -> guessBetween minAge (age - 1) + _ -> guessBetween (if age == minAge then age + 1 else age) maxAge + + main :: IO () + main = do + guess + putText "Thanks for playing!" +#+END_SRC + +So going from there we declared the =guess= function to call the =guessBetween= +function with the two paramters 0 and 120 to guess an age between 0 and 120. + +And the main function is a classic recursive function. +We ask for each age if the user is younger than some age. + +the =let= keyword permit to introduce pure values in between =IO= ones. +so =age = (maxAge + minAge) `div` 2= is mostly straightforward. +Note that we manipulate =Integer= and so that mean =`div`= is the integer division. +so =3 `div` 2 == 1=. + +We see that working in IO you can put print statements in the middle of your +code. First remark we used a recursive function. In most imperative programming +languages explicit loops are preferred to recursive functions for efficiency reasons. +That shouldn't be the case in Haskell. + +In Haskell recursive functions are the natural way to program things. + +Important Remarks to note: +- to test equality we use the =(==)= operator. +- Haskell is lazy, so the =age= value is only computed if needed. So if you are + in the case where =minAge == maxAge=, =age= value is not evaluated. +- In Haskell =if .. then .. else ..= form always have an else body. There is no + Implicit "no result" value in Haskell. Each expression need to return + something explicitely. Even if it is the empty tuple =()=. + +So now here we go: + +#+BEGIN_SRC + > stack build + > stack exec -- guess-exe + Are you younger than 60? + y + Are you younger than 29? + n + Are you younger than 44? + y + Are you younger than 36? + n + Are you younger than 39? + n + Are you younger than 41? + y + Are you younger than 39? + n + You are 40 + Bye! +#+END_SRC + +We see we can still make the program better. +For example, the same question is asked twice in that example. +Still, it works. + +*** TO-CLEAN Guess a random number + +Let's write another slightly more complex example. +Instead of guessing the age of somebody. +This will be the role of the user to guess a random number choosen by the +program. + +First we'll need to generate random numbers. +To that end we'll use a the =random= package as a new dependency. + +You can get more information either on hackage or on stackage: + +- https://hackage.haskell.org/package/random +- https://www.stackage.org/lts-11.7/package/random + +Hackage is the official place where to put Haskell public libraries. +Stackage works in conjunction with =stack= and mainly it takes care of having a +list of packages version working together. +So that means that all packages in an LTS (Long Term Support) release can work +together without any build conflict. + +Now let's use that package. +Notice the added =--package random= argument. + +We'll start by writing a =guessNumber= function: + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + --package random + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + + import Protolude + + import System.Random (randomRIO) + + ... + + -- | Choose a random number and ask the user to find it. + guessNumber :: IO () + guessNumber = do + n <- randomRIO (0,100) + putText "I've choosen a number bettween 0 and 100" + putText "Can you guess which number it was?" + guessNum 0 n + + -- | Given a number of try the user already made and the number to find + -- ask the user to find it. + guessNum :: Int -> Int -> IO () + guessNum nbTry nbToFound = undefined +#+END_SRC + +So for now we just focus on how to get a random number: + +#+BEGIN_SRC haskell + do + n <- randomRIO (0::Int,100) + -- do stuff with n +#+END_SRC + +You NEED to use the =<-= notation inside a =do= bloc. +If you try to use =let n = randomRIO (0,100)= it will fail because the +types won't match. + +And that's it! + +Now to write the =guessNum= function, we'll write a classical recursive function: + +#+BEGIN_SRC haskell + -- | Given a number of try the user already made and the number to find + -- ask the user to find it. + guessNum :: Int -> Int -> IO () + guessNum nbTry nbToFound = do + putText "What is your guess?" + answer <- getLine + let guessedNumber = readMaybe (toS answer) + case guessedNumber of + Nothing -> putText "Please enter a number" + Just n -> + if n == nbToFound + then putText ("You found it in " <> show (nbTry + 1) <> " tries.") + else do + if n < nbToFound + then putText "Your answer is too low, try a higher number" + else putText "Your answer is too high, try a lower number" + guessNum (nbTry + 1) nbToFound +#+END_SRC + +Let's read the program line by line: + +- ~putText "What is your guess?"~ should be straightforward. +- ~answer <- getLine~ So the ~getLine~ read from standard input and returns the + line entered by the user. The line will be put in the ~answer~ variable. +- ~let guessedNumber = readMaybe (toS answer)~: there are a few things to tell about this line. + +If you open GHCI and ask the type for each interresting symbol here is what you get: + +#+BEGIN_SRC + λ :t getLine + getLine :: IO Text + + λ :t toS + toS :: StringConv a b => a -> b + + λ :t readMaybe + readMaybe :: Read a => GHC.Base.String -> Maybe a +#+END_SRC + +- ~answer~ comes from ~getLine :: IO Text~ so ~answer~ should have the type ~Text~. +- Now we want to read this ~Text~ and see if this is a number and compare it to another ~Int~. +- To transform the number we don't use a function ~textToInt~ we simply use a + quite generic function ~readMaybe~ that take some ~String~ and try to + transform that to some type. For our specific case, the compiler is able to + figure out the type we want to transform the text into is ~Int~. Take the + time to digest that: ~Int~ is specified in the type signature of the + ~guessNum~ function so the compiler could discover that ~readMaybe~ should + return a ~Maybe Int~. How does he do that? Let's follow: + 1. see a ~n == nbToFound~ so we can deduce ~n~ and ~nbToFound~ have the same type. + 2. Reading the type signature of the function it is clear ~nbToFound~ is of + type ~Int~ (it's the second argument of a function with type ~Int -> Int -> IO ()~) + 3. Then ~n~ is generated from a pattern matching; the case ~Just n~ which + could be the the result of the ~readMaybe~ function. So we can deduce + that the ~a~ in the type signature of ~readMaybe~ is ~Int~ for this specific case. +- so ~guessedNumber :: Maybe Int~, if the user enter something that cannot be + transformed in number from a string then ~guessedNumber~ would be equal + to ~Nothing~ and we ask the user to enter a number. If the user entered a + number the type will be ~Just n~ were ~n~ will be an ~Int~. +- We compare the ~guessedNumber~ to the number to found ~nbToFound~. +- If the user found the right number we stop here by displaying the number of try. +- If the user hasn't found the number, depending on its value we tell the user + it's either too low or too high and we call the same function, this time, we + increment the number of try. + +The full program is then: + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + --package random + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + + import Protolude + + import System.Random (randomRIO) + + main :: IO () + main = guessNumber + + -- | Choose a random number and ask the user to find it. + guessNumber :: IO () + guessNumber = do + n <- randomRIO (0,100) + putText "I've choosen a number bettween 0 and 100" + putText "Can you guess which number it was?" + guessNum 0 n + + -- | Given a number of try the user already made and the number to find + -- ask the user to find it. + guessNum :: Int -> Int -> IO () + guessNum nbTry nbToFound = do + putText "What is your guess?" + answer <- getLine + let guessedNumber = readMaybe (toS answer) + case guessedNumber of + Nothing -> putText "Please enter a number" + Just n -> + if n == nbToFound + then putText ("You found it in " <> show (nbTry + 1) <> " tries.") + else do + if n < nbToFound + then putText "Your answer is too low, try a higher number" + else putText "Your answer is too high, try a lower number" + guessNum (nbTry + 1) nbToFound +#+END_SRC + +which once executed: + +#+BEGIN_SRC + > ./guess_number.hs + I've choosen a number bettween 0 and 100 + Can you guess which number it was? + What is your guess? + 50 + Your answer is too low, try a higher number + What is your guess? + 75 + Your answer is too low, try a higher number + What is your guess? + 90 + Your answer is too high, try a lower number + What is your guess? + 83 + Your answer is too low, try a higher number + What is your guess? + 87 + You found it in 5 tries. +#+END_SRC + +**** TO-CLEAN What did we learn so far? + +So up until now, if you followed. You should be able to "reproduce" and make +minimal changes. +But I am certain than it still be difficult to make some changes. +It is time to learn some general principles. +I know it might be a bit repetitive but its important to be certain to ingest +those informations. + +A generic function of type ~IO ()~ typically =main= should look like: + +#+BEGIN_SRC haskell + f :: IO a + f = do + α <- f1 + β <- f2 + γ <- f3 + δ <- f4 + f5 +#+END_SRC + +where each expression =fi= is of type =IO a= for some =a=. +You can use any value =α=, =β=, etc‥ as a parameter. +In order to be valid. +The last expression must have the same type as =f=. +so here =f5 :: IO a=. + +Now if I give you the following functions: + +- ~getLine :: IO Text~ that read a line from stdin. +- ~putText :: Text -> IO ()~ that read a line from stdin. + +With that you have the ability to read stdin and print things. + +- ~if τ then f1 else f2~ where =τ :: Bool= and the type of ~f1~ and ~f2~ must be the + same. Generally this is denoted by: =:type f1 ~ :type f2= and that type + will be the same as the entire ~if ‥ then ‥ else ‥~ expression. +- you can compare things that can be compared with ~<~, ~<=~, ~>~, ~>=~, ~==~, ~/=~ (different). +- you can concatenate things that could be concatenated (like Text) with ~<>~ +- you can transform things as Text with ~show~ in particular numbers. + +So that is a few number of component but they are all composable. +And so far we only needed that to write our first programs. + +Haskell libs will provide you with a lot more base functions but also a lot more +composition functions. + +*** TODO Command Line Application + +Another thing you might want to achieve at first is to retrieve arguments for a +command line application. + +**** TO-CLEAN Basic + +The simplest way to retrieve parameters to a command line is to use the ~getArgs~ function. + +#+BEGIN_SRC haskell + getArgs :: IO [String] +#+END_SRC + +Here is a minimal example. + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + -- stack --resolver lts-11.6 script + {-# LANGUAGE OverloadedStrings #-} + {-# LANGUAGE NoImplicitPrelude #-} + import Protolude + import System.Environment (getArgs) + + main :: IO () + main = do + arguments <- getArgs + case head arguments of + Just filename -> die ("The first argument is: " <> toS filename) + Nothing -> die "Please enter a filename" +#+END_SRC + +#+BEGIN_SRC + > ./cmdline-basic.sh foo + The first argument is: foo + > ./cmdline-basic.sh + Please enter a filename +#+END_SRC + +If you have a very basic command line it could be good enough. +But if you plan to have more things to configure you can consider +to use a library to parse options. + +**** TODO Option Parsing + +For that we will use the =optparse-generic= package. + + +#+BEGIN_SRC haskell + #!/usr/bin/env stack + {- stack script + --resolver lts-11.6 + --install-ghc + --package protolude + --package optparse-generic + -} + {-# LANGUAGE NoImplicitPrelude #-} + {-# LANGUAGE OverloadedStrings #-} + import Protolude + import System.Environment (getArgs) + + main :: IO () + main = do + arguments <- getArgs + case head arguments of + Just filename -> die ("The first argument is: " <> toS filename) + Nothing -> die "Please enter a filename" +#+END_SRC + +*** TODO File Access +*** TODO Daemons & Logging +** TODO Intermediate +*** TO-CLEAN Stack template + +☞ As a first projet a lot of new concept will be introduced. Don't be +discouraged by that. + +Let's create a project with a sane and modern file organisation. + +I made a stack templates largely inspired by =tasty-travis= template. It will +provide a bootstrap for organizing your application with tests, benchmarks and +continuous integration. + +This template provide a file organisation for your projects. + +Mainly do jump into programmin you could theoretically just download the binary +of the main Haskell compiler GHC to your compiler and compile each file with +=ghc myfile.hs=. But let's face it. It's not suitable for real project which +need more informations about it. + +So let's start with a sane professional organisation for your files. + #+BEGIN_COMMENT -/THIS IS A WORK IN PROGRESS/ - -*CONTRIBUTORS* - -- To extract all source code files do ~org-babel-tangle~ (, b t) in spacemacs -- To go to an imported file use (, ') - -Audience of this book: - -- people that are asked to work in Haskell but don't know much about it -- people that already tried a bit of Haskell and want to go further -- people that need to make a professional level product with Haskell -- people that are ok not understanding every detail yet but need the job to be - done - -Book is not for: - -- Total beginner that just want to know what Haskell is about -- Haskell contributors that already know a lot of things about Haskell - - -Goals: - -After finishing this book an reader should be able to: - -- script in Haskell instead of bash -- write a REST API with a swagger documentation and deploy it -- perhaps write a frontend app (I don't know looks like a LOT of work) - +****** TODO modify the URL to use a better URL: torrent / IPFS #+END_COMMENT -#+Include: HWP/1_Introduction.org -#+Include: HWP/2_Install.org -#+Include: HWP/3_Intermediate.org -#+Include: HWP/4_Production.org -#+Include: HWP/5_Advanced.org -#+Include: HWP/6_Appendices.org +#+BEGIN_SRC shell + stack new guess https://git.io/vbpej +#+END_SRC + +After that, this should generate a new ~guess~ directory with the following +files: + +#+BEGIN_SRC + > tree + . + ├── CHANGELOG.md + ├── LICENSE + ├── README.md + ├── Setup.hs + ├── guess.cabal + ├── package.yaml + ├── src + │ └── Lib.hs + ├── src-benchmark + │ └── Main.hs + ├── src-doctest + │ └── Main.hs + ├── src-exe + │ └── Main.hs + ├── src-test + │ └── Main.hs + ├── stack.yaml + └── tutorial.md + + 5 directories, 13 files +#+END_SRC + +Most of your source code should be in the =src= directory. Generally =src-exe= +should be a minimal code that could handle the =main= function to start your +application. We'll talk about other parts later in the book but most other file +should be quite straightforward. + +Edit the file =src-exe/Main.hs= + +The file contains: + +#+BEGIN_SRC haskell + import Protolude + + import Lib (inc) + + main :: IO () + main = print (inc 41) +#+END_SRC + +To compile it do a + +#+BEGIN_SRC + > stack build + > stack exec -- guess-exe + 42 +#+END_SRC + +So that program print 42 and stop. + +*** TODO DB Access +**** NoSQL (Redis looks easy) +**** Stream DB (Kafka or NATS, etc...) +**** SQL (SQLite & Postgres) +Not sure about that part. Perhaps this should move in the Production section +*** TODO REST API +**** TODO Servant +**** TODO JSON manipulation +**** TODO Swagger-UI +** TODO Intermediate Conclusion + +Congratulation for going this far. Now you should be able to work in Haskell at +least as well as in any other programming language. + +Now there are different directions: + +- learning more libraries +- learn to optimise code to make it as fast as C +- learn to understand details of the compilation and Haskell +- learn tips and tricks +- learn more about abstractions and type classes +- learn parallel and concurrent programming +- learn to deploy like a pro using nix + +The order in which to learn all thoses things can be very different for everty need. +#+TODO: TODO TO-CLEAN TO-REVIEW | DONE +#+LANGUAGE: en +#+KEYWORDS: haskell +#+PROPERTY: header-args :output-dir HWP :mkdirp yes :tangle-mode (identity #o755) + +* TODO Make Production Quality Products +** TODO Dhall /Maybe/ +** TODO Error Handling + +** TODO Unit testing / doctests +** TODO Generative Testing +** TODO Enhance reproductibility with docker +** TODO Enhance reproductibility with nix +** TODO How to deploy? + +There are plenty of ways de deploy + +*** TODO Trashy and easy + +Compile in docker and copy the binary. + +*** TODO With =nix= and =nixops= +#+TODO: TODO TO-CLEAN TO-REVIEW | DONE +#+LANGUAGE: en +#+KEYWORDS: haskell +#+PROPERTY: header-args :output-dir HWP :mkdirp yes :tangle-mode (identity #o755) + +* TODO Enhance Code Quality +** TODO Type tricks + + +*** TODO New Types +*** TODO Phantom Types +** TODO Useful Abstractions +*** TODO Monoid +*** TODO Functors +*** TODO Applicative +*** TODO Monads +*** TODO Arrows +*** TODO Foldable +*** TODO Traversable +** TODO Useful Abstractions for Applications +*** TODO No organisation, everything in IO +*** TODO Handler Pattern + +See the talk from Jasper Van Der Jeught + +In my opinion as efficient as MTL, Free, Effects, but with more verbosity and +repetitions. + +*** TODO Custom Monad +*** TODO MTL +*** TODO Free +*** TODO Effects +** TODO Lenses + +This will only be an introduction for being an user of the library. + +** TODO Generics and lens-generic +** TODO Code organisation +*** TODO No organisation, everything in IO +*** TODO Custom Monad +*** TODO Handler Pattern +*** TODO MTL +*** TODO Free +*** TODO Effects +** TODO Recognize some classical abstractions +*** TODO Algebra +*** TODO Catamorphisms +*** TODO Free & Interpreters +#+TODO: TODO TO-CLEAN TO-REVIEW | DONE +#+LANGUAGE: en +#+KEYWORDS: haskell +#+PROPERTY: header-args :output-dir HWP :mkdirp yes :tangle-mode (identity #o755) + +* TODO Appendices + +** TODO Papers You Should have read diff --git a/TODO.org b/TODO.org index 6e648860..68b25e7e 100644 --- a/TODO.org +++ b/TODO.org @@ -1,6 +1,6 @@ #+Title:TODO #+Author: Yann Esposito -#+TODO: TODO IN-PROGRESS WAIT | DONE CANCELED +#+TODO: TODO IN-PROGRESS HOLD WAITING | DONE CANCELED #+COLUMNS: %TODO %3PRIORITY %40ITEM(Task) %17Effort(Estimated Effort){:} %CLOCKSUM %8TAGS(TAG) Paris 7h10 - 8h45, à Londre, 15 mars @@ -29,7 +29,6 @@ Les languages de programmation fonctionnels ont introduits récemment l'usage de structures de données immuables. Nous verrons comment celà facilite énormément l'écriture de programmes parallèles et concurrents. - *** DONE Virement maman 3000€ CLOSED: [2019-03-29 Fri 09:23] - IBAN: FR28 3000 2028 2100 0005 8155 N89 @@ -58,8 +57,8 @@ l'écriture de programmes parallèles et concurrents. Tel: 09 80 89 95 31 ** Meetup Lamda Riviera :geek: -** Projects :dev:geek: -*** TODO Write a comments system +** Projects :dev:geek: +*** IN-PROGRESS Write a comments system Requirements: @@ -109,7 +108,8 @@ Requirements: https://man.sr.ht/installation.md) - Something rawer like gpm? **** TODO Enhance Domain Name hoster to better support letsencrypt (typically CAA I think) -*** =gpm= todo / wiki / docs, etc... :dweb: +*** CANCELED =gpm= todo / wiki / docs, etc... :dweb: + CLOSED: [2019-04-14 Sun 20:00] **** DONE Doc CLOSED: [2018-11-17 Sat 13:07] Write a tool to handle the following workflow. @@ -165,8 +165,8 @@ Requirements: CLOSED: [2019-03-03 Sun 15:08] ***** DONE Ignore patterns CLOSED: [2019-03-02 Sat 20:07] -***** TODO [#C] Use a split and Index on n-grams to match for all bots fast -***** TODO [#C] User regex? +***** HOLD [#C] Use a split and Index on n-grams to match for all bots fast +***** HOLD [#C] User regex? **** TODO Enhance Producer by retrieving all post/comments [[https://intoli.com/blog/f5bot/][f5bot]] **** TODO Send mails on matches **** TODO Dev/Ops Improvement diff --git a/agenda.org b/agenda.org new file mode 100644 index 00000000..638140fa --- /dev/null +++ b/agenda.org @@ -0,0 +1,13 @@ +* Agenda +** TODO yet another thing to test + :LOGBOOK: + CLOCK: [2019-04-15 Mon 00:35]--[2019-04-15 Mon 00:35] => 0:00 + :END: + [2019-04-15 Mon 00:35] + [[file:~/.spacemacs::'(org-agenda-files%20'("~/.deft/agenda.org"))]] +** TODO xxx + :LOGBOOK: + CLOCK: [2019-04-15 Mon 00:36]--[2019-04-15 Mon 00:36] => 0:00 + :END: + [2019-04-15 Mon 00:36] + [[file:~/.spacemacs::'(org-refile-targets%20'((nil%20:maxlevel%20.%209)]] diff --git a/cisco-epic-feature-flag-by-env.org b/cisco-epic-feature-flag-by-env.org new file mode 100644 index 00000000..e00a5e85 --- /dev/null +++ b/cisco-epic-feature-flag-by-env.org @@ -0,0 +1,72 @@ +#+Title:Cisco Epic Feature Flag by Env +#+Author: Yann Esposito +#+LANGUAGE: en +#+TODO: TODO IN-PROGRESS WAIT | DONE CANCELED + +* Feature Flag by Env :TOC_3_gh:QUOTE: +#+BEGIN_QUOTE + - [[#requirement][Requirement]] + - [[#current-status][Current status]] + - [[#proposed-solution][Proposed Solution.]] + - [[#feature-flag-block-in-configedn][Feature Flag Block in =config.edn=]] +#+END_QUOTE + +** Requirement + +> Craig Brozefsky Yesterday, 17:04 +> Matt: No orgs in EU should have devices scope + +*** Current status + +Until now we managed feature flag for an entire release. As such the +feature-flag was 100% held in the code, not in the deployement conf. + +There are two methods used until today to manage feature-flags: + +1. scopes +2. service launch (in bootstrap.cfg) +3. control via config (in config.edn) + +The current requirement only talks about the =sse= scope. +In fact we could (should) also prevent the =sse-service= to be launched. + +Note that scope handling is generally not trivial: + +- CTR use the scope as the single dimension to handle authorizations. One + consequence is that the notion of /role/ is not really meaningful in the CTR + code. The /role/ is only used from the info provided by the IdP and then + interpreted as a set of scopes (which can change dynamically, for exemple we + can attribute additional scopes to some org or user). It is also planned to + provide the ability for admin users to change the scopes of other users of + their org. + +** Proposed Solution. + +*** Feature Flag Block in =config.edn= + +That way it would be possible to not only handle scopes but also manage the +feature flag in some specific part of the code. Typically we could use that flag +to ignore some conf, and to not initialize fully some service. + +**** Service Launch Handling + +- If a service is started but its presence is not necessary when the feature + flag is off. The service should not really init itself fully and only return a + nil context and the methods should also returns nil silently + +**** Scope Handling + +Depending of the feature flag we might add an additional step during login we +might "add" some new scopes and "remove some". If that's the case we might also +change the JWT version dyamically. + +I would suggest something like: + + +#+BEGIN_SRC clojure +(defn dyn-jwt-version [activated-features] + (string/join "-" (cons static-jwt-version activated-features)) +#+END_SRC + +That would produce version such as: =v1.23=, =v1.23-sse=, =v1.23-sse-scim=, +etc... diff --git a/journal.org.gpg b/journal.org.gpg index 04a26dc69bdf882ced0397c7bdd20331ed45c64e..6d7edb5c26bc82819098e8014691bc628c35fa48 100644 GIT binary patch literal 6721 zcmV-H8ouR)0t^FvF6E%v-!tL?5B@pOK?jmL(ZGn(>Zr-EtB>tGYw9yvp3w3|! zWSB=tG3h9z_M7&i-jjUP5&6dG1Z;)IB3iIK{|H0ky|f>z-x+_6dkB%p^yPF;GcS+p z()-%d+9RyI&0qHqga4dhjh4?A3mL|AKDJQ^FEB5O_iMk|is1%^tZ9KwtO_}+&9?Sl zZHnms$(&pXE1rP4xAx`T`28fLzCHogq=5ccGlqu&kw&+~d0$5-z#NQ^M&N7Hm_EZT zyAkHX)zHt9<}Eb1?Dd!Rgtx}C_9n9UQ-&8kAR|_8bLJHPfvnxQh`sRohcE?pxRudt z5!}@_szA*iQ?vv@%xW!IIzoGcX~_$QzT1Tn#d>qa+O(3Zk|4mK?um+Np44Ys@CHg} zMbS$}=PD!vF8uMeiPs928S&7hVI=Cbd}O3zi{Q);S9`w336slUcfE+2_GQ~@<~WgI z(IK|Yx&jyys{cpPJkNR9Ru}sY^Y$6a@?p)Ro;pbI7(7wxT*dD%M!ZyBr2UrOA{c7s zHt>$W%!>esq(A&vKhVQDr_~Y-=~C?;-9ILFr56Hg3#s>*$YW4Ll2NPhZ}7RcoDNY8h8K7F0L(#ryA61 zadG9NJ8D+>skS4K**zCcD)O;(s>@+5`NGybXF$4!tphun1R`mv)>F?*>FL#Vi-v|B zJ(AIp`&A(({#q+~5II2Y(VnyBYvENxN647{Ss3@UpR9P-_yHs!0QRNKu5SleNO*N7b%1;PRDo4rV?2>^205!e@?WK{< zZ6|L=q5vr8L7OBV0a0v0+~G_J4f{Wq`bjlz)w^ltHWf1>bq%wrJ__``Y^PB1ZmE1% zp^y=>Jr%n^oaU7$pX%IZv4F-jj5U@#>)pNX33{2)>H^l7(CX;nzvnZJuKTxj`hXV= z>2(~WQ>Yzdhsw-QZ9x+<9N?&`w)CM)p(NTB%P`4UP{w0LQKZthxoab81f`<4E{|Irho*YkcmEGvs=D(JS4X2qA9~ zo7NsYnBE**<6nOi9-P~EB=R_#DF2NbLFWhOrC@`9JWMWYpv@^~wL)m&Dmpm!enJB) zUV+aXSlvAr`;hv@;J?g#GbpmjqW0iDLzT)*_LQ*cz7+8U;8G+HAw0Cejwzitc6T7s z2;P*dER%)_(k#8U97f=N8?>&>l+$5P3+ft3o7=$UQY8>AkI?{mmO;ugW;VirtNZ8E zVX7I08|WVGBK8hZEQezO5o#@JDc~rEzwOPsity430$DEvP`q~H3f;ryVb!+{R{cV3 z?JGQ-)=Xh1D~mLb%W|$6dhumw?mJ(S%RdeB3Q7VZN|#Rm9zX<-ia>jv{an^PrYTI! zgH4V>hOuEGG>|$HnJ$GP_k3dULAH9t+ar0Tk{X?l5VSxv4Kh6$Y5F5HX42iSWNh<+r~SK;l`h=XaxO6cUD&m4 z$*!=|Vf0&9g7}j8<)!UMj(o4HA$;>c(RBDcj-F7aim55g<*((S5ySWe=s@$OvQV$3t;4_aneG{!vh)xi0?3}!3*!} z_x(LPTvhZe`e6Piwb|6PfoLF9N`k^IO}ugeX^&HZ{$o;r{{`sVN?S(6~wyJMMVF!z0b|HO!TZx2`r>!o0t$Up8haTJ! zLaJU09bZtzQz$$Ew(gnnOMG1N419+}l<@nT=M*dm)aKsiuKJ@}|I$EcLl6;JBR^Qo zA!2-Q;dFRKTqz{pB5k?>5OFBF^rzR>V{g*QzEu2JrD00Troh>&b+nfmesf5j&`z(` zhCU<3z&03B-tjls6bEeRi$1Y>`)1~sDeI55-P_sE$qTeJs5aIo?wTC~7B{_0<5CI! z0@9bE{j~9tMNzw{NVvt_Mwdox%(CS<0@a+#NLsOdx^kEcGvEo*Egr%%eIVty^QCvLrU4tp z8z?9I3b_BPSmVcebGlBhM_AeV3aZL+xPqOnbNBeEY{5KcZGPIcJao)2vrXf z_;1I1L{|wAn*$)z>7#nXktK4@o^W^ki_`6?c(xX7bX5rsg8LR6EigS@l|H+hyHV|5 z{};~WXzVxoLKI8zt=mWWTA)^fiEgYqOdhT|wMAX0$?^9f%3*>c@S$Wlj0>#~D!?6i z%cJ2tQ@#Vf!BW(&+?HkxGV}ZTJZ$hO^Pb?8fL&75%2Fi_?f0Ge6uLGJFT}aZC1FU9 zeWq<{7q9#TR1b)C!(J+e&2Vz)F@@x31dpNI5hJ1jbJXmDBiw`_5cj%4SAmU6326xr zNiK=~chsA&MD3-~cV?czP#ZIwO8bg}2Zm82YTQ3VJ-haUc?9^l??>|nmoK42 z4|hZCDU(%?5Wa%zrSQ#!!Rdm1qzvP|ZpPz@0d>_wZgadd@{}bmUzUF*#dk80@&LaC za?jJrozWKd9T+6va*_mgjmYr`s)C41{JKCGDJJRlCF<1c`%$DN0f7LNvr|uJ{tr{8 z3MMxi?;P%W_F}V^^ebe_W_Y@#%zSEvp9G-6u+Ez%(2vM-o}hUM z+DALJxGsDLgEI*)gN7}bB%SgMq`c0odQ_%0fE^lYas48B;heWhy&-OC2-T2XN4%0B za1(1gsm54Vy9S0%U_ZX3G}d*TINOlhqfT3@@3i>FW9sWeayr8DFGbt&TH-{8sr6?V zS^pr{t@z!_;q%ag-~LYdGP>~o=g&E@%;DR%9P7^DWozTR8h)7!B87q8^Df+7&XL*S zl9W>yr_(0oPEQh0x16OY)A0opt`i8B7o_v>SD1bM>HSObmu;sI}mKK#VkzFy7@;Gxc?$+ehs6J%u? zWmMzH_f6S}I|N8CI@bAv>Z$8Z3G{uwvQg^3kCdh|?3 z;Z@MiHdGOCcPPLM%IzRNQ4kvE_-oJLO^)+0=l=cU)ASw=0*wjW+L_tXY71$mD1RShU<^paD&|zpOgzQ zy1<6UcT+;*uHRC3_5IxUEibhQ9UI946|Itkjc3YwC6a}(*luf>!YCqL3VNLl2g$$BRMlUr^#eo{Y*v=RZ3-dZ@402V2y$KF^0?8G++Ah7vUMc2o81 zu@QuENM9H4PXKtw_sgty4#a0St>oeFHLD}aB3r2g_5uBZB;CO+x~qW=JsP* z(tq`4R+XUvZ;^k^4L727u4+3mhh8j;qf0|2p+EW46WttzqxN3dhcE2D;Y)6W7YhB< zjMWh6Eq2o$NHbVBv&-Xdd=4!+C$BrzTCkdu*g>`~Sv@5o*5@>uXFm2a^tg#L;JBjm z^G)**&^mgcgIaz`oVJbjcoL&>zY_Jzgt=y!W@iKzh)!wF_4yGzr z|2KUr1^JXO96LEKg{la|G$qtD0s`C!M23PqF8B56Q@<*$M*IQbhoAVKo20}``rAfNsx|PluHU0=xXxA z<~}I2K+*R(Gmd@FNT;=1a5E{EIu__~{xNdsVef;o?9;io`*^8B)IP+*ke6*ylcc~v z-!k;ljSqoCX*-WEu5l#j!#UmBcJXqfD$`Cw;Xt!nt80|WB}m?4A1NoHSFJ${3F|OZ zw5VPBhevegQ32msIh$U8AS(g~a0ZqX@2CZ@)n(rEdOQaSt#&nmdTq2i8AcnO#x`U= z`csXeE~cg)6vq5yJ)X_~n!xVk|$B{vlBzMEP?YNY%CTjWcXz#zoIl>1Knmbg!e z@uq*2A18>@jPaCn?B?S++;kF&ECn6B0U=V)T}?F%V^-FAIm z4en=i>&PI1hazKk2NFWW*s3woamZUY){f+I*ZArVoMU`Q-qE2sRvo${}Cg6MSXaziw(6vQB^`D zrS_*$pRYEbfXDX*x{BzBON9|nNq7@7Nz*08G?BX3a9C+XtQDs_ot0>mUdzgyKw~tx zxAAVlMXp8LCn6eKbJ3-yJ3E68T;TMfQQ+n zUhEpx(Gd)cS$o^dGjg+4SpUd<5c>~mk8vi;NF-(JIH;2LjJxP(7BtyK68aCx{ z>EM0{S3m+iwuHTo&DuDLA+F=T{)2!tngh-V%{6!nJIj12R~6_4OJhV0!vASLzyo)_{ z8-zjvFd5uL^6Qc%!G(l0qGB~DE;x0Mfh*^OSSJBD zH?7f=xWd2XM#iTY(eMamPrDYo8QV9Epxj1%G)JNqqC8sCvi2K7x>OVux_E z4T_h5%JmL$mG(Ppi*k;*3DvpBc=zY$MBr{UHSkH-n~rocpzykY%YRTDE!@HxMw&WJ z99pb$ko-Js7%o|@f;pEdqM7lffJJF2Ss%+c)y(_1EGchc2^M$o^Z%>I^9hxFDCCq7 z5}@B$ChI5!5w9pNs39}ZEBUGnRW5GaAtVHn;)TwT2QznVb%_w78pRVojeUk6Q&Vnv zN|y}4|J={-?I{matiMrza_1s1EGskZ(KbeMo{f@a3Dj^qyi_yXB(S^f3&dqFt<{G? zmJoWMvHxIpoQ}@MXk-c%n!3Ub>J**I6)VGq;b)x(Q9vWODpB@mg2W+wJhQf)qdLFb zvzXqV2*+&S&e14cPS+^3F04H1X!%JE#a|l7^Y;%U(%V zrs$wDHB1GPpmCbA`mB3g`W(2XAFGFBm`?sV>G?<1OA9s|qMib;AE(ow-~z#08~*1% zMV$9KrUK2>to9#;-el(Bv>+pN0V$Dp(kYf{rCD{{g7EwqBWY3)G@MdxUX$u3SR}~% zR*6u?jsoht7}|Hs2zKT!%6;@%SSHxFWuuG+rDHyfJ*D?VVo~v}`r6({hwfrK&L5W6 z@tWZ$_~27F6#3ftM?o|{*r@KS;SNKwH3zb4$Zz)>W0G0xesO2|K{al`#fDv>v?MGR zQkxLz%41J7=?>w!?Y*yl}eSGn3lke9iIJW6Z?w%?K#2gG4(uu^jKA&Q1@7!LsF4?l?&K6K4!O zwwOQlPt7`;$aJEZqwmttCxBSP4B#s%=`VKC0I>xD&2#j_3iwVZ(LLGFPyVcA)&-K9 z1AY84W%Yz=fIeL{L-2_>3WjN8_5E&cb%;WeyDB2OWn(*Yv_u*|O8bHt5RA2_Jt2?3bHg$St>{vQXe-8dDW6oMvgLkPLpg{rSz z6>C65Q~W=~&7 z=DUh34TG7gBuDFbsFGjl;VI*%duVT&k+e7l`7U8nIFV1?G3q0~Bk@AwNK){TOK8I_bDI|s XKvT0#r@_;^lQ5$IjIR7R_cbB{h7~@C literal 6719 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 VC)N=tm7xC4qBIIikemvFW(L_r*rxyh diff --git a/refile.org b/refile.org new file mode 100644 index 00000000..6c39ee17 --- /dev/null +++ b/refile.org @@ -0,0 +1,4 @@ +#+FILETAGS: REFILE +* Tasks +* Notes +* Agenda