Supporter Talk by Chime: Coordinate Ruby Teams With Chime

Summarized using AI

Supporter Talk by Chime: Coordinate Ruby Teams With Chime

Noel Rappin • November 13, 2024 • Chicago, IL • Talk

Overview

In the talk titled "Supporter Talk by Chime: Coordinate Ruby Teams With Chime" at RubyConf 2024, Noel Rappin from Chime's "I Heart Ruby" team explores strategies for effectively managing Ruby development across numerous projects within a large-scale financial services environment.

Key Points

  • Purpose of the iHeart Ruby Team:

    • The team focuses on enhancing the developer experience specifically for Ruby developers at Chime, a company that serves those underserved by traditional banks.
  • Ruby Development Challenges:

    • Managing hundreds of Ruby gems across multiple services presents dependency management difficulties.
    • The architecture is neither fully microservices nor monolithic, comprising over 50 separate Rails applications.
  • Dependency Management Solutions:

    • Rappin discusses the development of a dashboard to visualize the state of Ruby dependencies across services, highlighting problem areas in updating gems and Rails versions.
    • Metrics are captured such as how many versions of Rails are in production, how many teams are behind on dependencies, and tracking progress over time to enable better planning by teams.
  • Implementation of the Dashboard:

    • The dashboard aggregates data from various repository files, providing insights on the gem dependencies and their compliance with set policies.
    • Features of the dashboard include tracking pull requests, gem versions, and generating reports to foster accountability and better upgrade practices among teams.
  • Lessons Learned and Adjustments:

    • Definition of "out-of-date" dependencies as having a grace period of 90 days plus end-of-quarter, allowing teams to plan appropriately for upgrades.
    • Challenges in parsing different Ruby configuration files, with bundler files being more straightforward compared to gem specifications created by developers.
    • The success of implementing Dependabot to automate minor gem updates, revealing areas of improvement.
  • Techniques for Handling Personally Identifiable Information (PII):

    • In the latter part of the session, Brandt discusses strategies for preventing PII from being logged and shared, thus ensuring customer privacy and compliance.
    • Introduces the concept of a wrapper object for attributes that needs to mask sensitive information while still allowing for debugging and system compatibility.

Conclusion

The session concludes with the importance of collaboration and planned upgrades to maintain dependencies effectively, alongside implementing systematic privacy measures across services to protect personal data.

Supporter Talk by Chime: Coordinate Ruby Teams With Chime
Noel Rappin • November 13, 2024 • Chicago, IL • Talk

Coordinating hundreds of Ruby developers on dozens of projects can be challenging. Join members of Chimes "I Heart Ruby" team as we discuss some of the ways that we help our teams coordinate their Ruby tooling.

RubyConf 2024

00:00:15.280 hey all right uh thank you uh on behalf
00:00:18.560 of Chimes iHeart Ruby team which is
00:00:20.640 myself and Brandt over there say hi
00:00:22.599 brand uh Welcome to our Welcome to our
00:00:25.720 sponsor session here uh we also have a
00:00:28.279 couple of other chime employees here if
00:00:29.720 you could also other time employees
00:00:31.800 raise your
00:00:33.879 hand okay a significant percentage of
00:00:36.680 the audience is time employs and have
00:00:38.800 heard much of this before uh chime is a
00:00:42.879 financial services company that uh
00:00:45.640 targets people who are otherwise uh not
00:00:49.680 well not well served by the traditional
00:00:51.680 banking system um people who are working
00:00:54.800 who are living paycheck to paycheck uh
00:00:56.920 people who are really uh looking for or
00:01:00.399 an option that does not involve uh being
00:01:03.280 a part of the traditional banking system
00:01:05.239 we solve a lot of hard and complicated
00:01:07.360 problems to try and make things as easy
00:01:09.119 as possible for our members uh if that
00:01:11.479 interests you at all please come and
00:01:13.240 talk to one of us about opportunities uh
00:01:15.799 that you can have at chime um I will say
00:01:19.560 the signage says that we're going to be
00:01:21.119 at the job fair we will probably not be
00:01:23.439 at the job fair um but any of the people
00:01:26.960 uh walking around with chime t-shirts uh
00:01:28.920 will be happy to answer your
00:01:30.759 questions so uh I said that we're part
00:01:34.000 of the iHeart Ruby team uh which I think
00:01:36.320 begs the question of what an iHeart Ruby
00:01:38.560 team actually is uh and uh I describe it
00:01:42.920 as Chimes developer experience team the
00:01:45.159 part of Chimes developer experience team
00:01:46.680 that is specifically targeting Ruby
00:01:48.920 developers and Ruby tooling so uh that's
00:01:53.040 kind of my Lookout and brand has joined
00:01:54.840 just recently joined the team and that's
00:01:56.119 what we try to do for Chimes uh you know
00:01:59.399 several 100 Ruby engineers and several
00:02:02.000 dozen Ruby teams and so that involves a
00:02:04.240 lot of different things we're going to
00:02:05.360 talk today about dependency management
00:02:06.840 we're going to talk a little bit about
00:02:08.000 internal tooling uh we also sort of own
00:02:10.840 internal Ruby standards and practices we
00:02:13.280 do some internal Community Management we
00:02:15.040 run Ruby onboarding we monitor slack for
00:02:18.120 General Ruby questions and get pinged
00:02:19.920 whenever people have whenever somebody
00:02:21.440 has a problem with bundler or something
00:02:22.920 like that um so it's a wide variety of
00:02:25.560 stuff that we do to support uh Ruby
00:02:27.920 development at chime and I'm going to
00:02:30.160 talk about one of our pieces today and
00:02:31.440 Brandt is going to talk about another so
00:02:34.840 uh I'm going to talk about the problem
00:02:37.160 that we have uh managing gems across
00:02:39.640 services so chime is not exactly a
00:02:41.680 microservices architecture but it's not
00:02:43.640 exactly not a microservices architecture
00:02:46.480 we have you know over 50 separate rails
00:02:49.640 apps running internally in our codebase
00:02:53.000 um which leads to you know there are
00:02:55.200 some advantages to that in terms of
00:02:57.080 taking advantage of The Sweet Spot in
00:02:59.000 terms of the size of of rails
00:03:00.239 applications but there are definitely
00:03:01.519 some disadvantages in terms of
00:03:03.519 dependency management across all of our
00:03:06.159 different services and in particular uh
00:03:09.560 we use hundreds and hundreds of ruby
00:03:12.760 gems I believe if you count our internal
00:03:14.599 gems the count is is over a thousand I
00:03:16.640 think we just pinged over a thousand I
00:03:18.480 think that's going to be true of any
00:03:19.720 large scale uh rails application uh and
00:03:23.519 those gems are continually going out of
00:03:25.640 date we need to continually monitor
00:03:27.480 stuff we try to get teams to keep
00:03:30.480 uh especially the most important we try
00:03:32.840 to specify preferred versions of the
00:03:34.720 most important gems but there's a bunch
00:03:37.040 of different services and the question
00:03:38.560 becomes like how do you how do you
00:03:39.840 monitor them so keeping that keeping
00:03:42.120 everybody on that same page is a bit of
00:03:44.439 a
00:03:46.239 challenge one important part of that
00:03:48.760 process for us has been trying to
00:03:51.799 visualize what that entire ecosyst what
00:03:54.480 our entire ecosystem looks like uh we we
00:03:57.599 came to the conclusion that it was it
00:04:00.159 was much easier to manage the problem
00:04:02.400 once we had a sense of the scope of the
00:04:04.120 problem like where do we have problems
00:04:06.239 updating how big are these problems how
00:04:08.159 far behind our our our teams and things
00:04:10.760 like that and we had no real easy way uh
00:04:13.040 to answer that question systemwide and
00:04:15.519 so we built one we wanted to answer
00:04:17.079 questions like how many point versions
00:04:19.199 of rails do we have in production a
00:04:21.000 staggering number of Point versions of
00:04:22.800 rails are currently in production at
00:04:24.240 chime um how many teams are behind on
00:04:26.919 major dependencies like Ruby like rails
00:04:29.560 and and how far behind are they and most
00:04:31.759 importantly are we getting better or
00:04:33.280 worse like are we keeping up with new
00:04:35.479 dependencies or is stuff getting updated
00:04:38.280 and we're just falling further and
00:04:39.440 further behind the thing about these
00:04:41.479 kind of dependencies is you always wind
00:04:43.039 up in a situation where you want to
00:04:44.840 upgrade on your schedule rather than
00:04:47.160 have the upgrade be forced on you
00:04:49.320 because uh some sort of dependency
00:04:51.720 management issue requires you to update
00:04:54.240 and scramble update a bunch of services
00:04:56.120 in a short period of time you trying to
00:04:57.720 avoid that eventuality so uh I want to
00:05:01.960 in order to generate first to generate
00:05:03.720 data and secondly to sort of manage this
00:05:05.600 process um I wrote a dashboard and I
00:05:07.880 took all of our repos and
00:05:11.039 uh wrote a data parser that grabs takes
00:05:14.880 all of our rails apps and all of our
00:05:16.280 internal ruby gems grabs their gem file
00:05:18.360 their lock file their gemspec their Ruby
00:05:21.080 version file their rails applications
00:05:23.120 config application RB because we were
00:05:24.759 tracking zit work adoption for a while
00:05:26.759 and we were getting it from there and
00:05:28.160 grabs their Docker file because in our
00:05:29.759 system the docker file is actually the
00:05:31.199 source of Truth as to what Ruby version
00:05:33.479 is actually being run in production um
00:05:35.759 and I wrote a big chunk of parsers that
00:05:38.039 gives every repo a dashboard like this
00:05:40.919 um it says for every repository it says
00:05:43.600 it gives them a score of how far behind
00:05:45.680 they are in general this is the reposit
00:05:47.199 this is one of the few ones that that
00:05:48.639 the comms team would let me show which
00:05:50.199 is the one for the dashboard itself
00:05:53.639 um uh it says how many you we've got an
00:05:56.600 activity monitor how many PR how many
00:05:58.360 poll requests have this have been uh uh
00:06:01.560 approved in this Jam in this repository
00:06:03.479 in the last 30 days it's telling me what
00:06:05.240 the Ruby version is what version of
00:06:06.440 bundler it's on you know J Malik rails
00:06:08.360 version and then for every gem we're
00:06:10.440 test for Every gem that it uses um is it
00:06:14.240 the current version if it's not the
00:06:15.639 current version when was the how far how
00:06:18.000 far is it behind the current version is
00:06:19.680 it out of policy which we'll talk about
00:06:21.160 in a second uh and then it sort of lists
00:06:23.160 all of them is it pinned uh is and and
00:06:26.160 and and specify for it the gem dashboard
00:06:28.000 because it's basically a team of me we
00:06:29.800 can keep quite up to date other of our
00:06:32.400 services have slightly spicier
00:06:34.160 dashboards um which they didn't really
00:06:36.400 want me to show you
00:06:38.520 um uh we also we we also on the flip
00:06:41.639 side can do the same thing for rails so
00:06:43.960 for any gem so we can also see this for
00:06:45.960 all of our gem dependencies we can see
00:06:48.000 what the current version of the gem is
00:06:49.560 when it was released how many
00:06:51.319 repositories are using it and then it
00:06:52.639 lists all the repositories and actually
00:06:54.520 it will also list all of the pins all of
00:06:56.479 the bundler um uh constraints that are
00:06:59.759 set so if something has it pinned to you
00:07:02.599 know Tia rail has pinned rails to Tia
00:07:07.319 7.0.0 or if it's you know we have some
00:07:09.960 hard some things that set hard ceilings
00:07:11.560 on gem versions uh we can see the list
00:07:13.680 of all of them um so yeah okay like this
00:07:18.039 um so it it has the pin and then we got
00:07:20.960 I got I got a request to actually
00:07:22.400 explicitly display the highest and
00:07:23.800 lowest allowed version which allowed me
00:07:25.520 to invent 6.1 Infinity is highest
00:07:28.680 allowed version of a gem um so there's
00:07:30.919 actually an object in here called fuzzy
00:07:32.560 version that allows you to specify
00:07:34.080 infinite sub versions which was fun um
00:07:38.199 uh we actually also now it didn't when I
00:07:40.160 put these slides together but I do now
00:07:41.599 have a specific report of like which
00:07:44.720 specific pins are causing us the most
00:07:48.479 constraint so you know if we have we
00:07:51.639 have a lot of gem we have a lot of
00:07:53.560 service we have a lot of services that
00:07:55.319 pin uh like an AWS gem because there was
00:07:57.960 a bug at one point we didn't go back and
00:07:59.960 put and and and we haven't gone back and
00:08:02.159 fixed it necessarily um but it can say
00:08:04.840 like how many services have that pin how
00:08:07.520 far behind it is and how much it's
00:08:09.000 costing us um we also we also can
00:08:12.680 specify reports for specific upgrades so
00:08:15.000 I can say like Define an upgrade of
00:08:17.720 anything that's still on Ruby 31 that
00:08:20.400 needs to get updated to Ruby 32 and I
00:08:22.199 can get a a nice listing of all of them
00:08:24.159 and and put some notes on it and then we
00:08:26.039 use it to track uh that behavior over
00:08:28.400 time there's also a Time ser graph that
00:08:30.080 I'm not showing here of certain Behavior
00:08:32.719 over time which is also the better or
00:08:34.479 worse question um so a couple things
00:08:37.680 that we learned from doing this um one
00:08:40.680 of which is it actually forced us to
00:08:42.360 Define explicitly what it meant for
00:08:43.959 something to be out of date um and what
00:08:47.200 what that that that's sort of a social
00:08:48.959 construct and not necessarily A
00:08:50.720 technological construct and we wound up
00:08:52.600 defining it as uh 90 days plus end of
00:08:55.959 quarter so if uh gem got updated
00:08:58.839 tomorrow the previous version of it
00:09:00.800 would still be like in policy and not
00:09:02.839 out of date for three months so that's
00:09:06.120 uh you know December January February
00:09:08.040 and then the end of that current quarter
00:09:09.680 so the out of the out of the date that
00:09:11.720 it would become out of policy would be
00:09:14.200 the end of March and the reason we did
00:09:15.720 the end of quarter bit was it's a social
00:09:18.160 reason it's to allow teams to look at
00:09:20.279 the beginning of a
00:09:21.560 quarter um and plan ahead all of the
00:09:24.000 things that they might need to upgrade
00:09:25.160 during that quarter and know that
00:09:26.560 nothing new is going to jump onto that
00:09:28.160 list because anything new will be part
00:09:29.760 will automatically part of the next
00:09:31.000 quarter so we we're g the idea here was
00:09:33.760 to give teams a little bit of
00:09:36.480 consistency in planning uh if they were
00:09:39.320 and to hope to encourage teams to plan
00:09:41.320 their own upgrades for all these tools
00:09:43.720 um in terms of like on the technical
00:09:45.480 side uh it turns out that parsing lock
00:09:47.839 files is actually quite easy uh bundler
00:09:50.320 provides a tool for it already because
00:09:53.079 bundler parses them um uh but actually
00:09:56.440 parsing the gem files and the gem specs
00:09:58.240 which are written by people is much more
00:10:00.160 complicated the gem spec because the gem
00:10:02.000 speec because the lock file is produced
00:10:04.680 by bundler it's much more consistent and
00:10:07.120 so the parsing of it is like very very
00:10:09.880 simple um a gem file or gem spec where
00:10:12.959 you have to worry about like are people
00:10:15.200 putting spaces after the operators as
00:10:17.200 they set up the constraints like that
00:10:18.720 gets a lot more that gets a lot more
00:10:20.040 complicated and and to the extent that
00:10:22.079 you can avoid doing that is definitely
00:10:24.079 worth the time period um and we actually
00:10:26.720 and it actually turned out that we were
00:10:27.800 doing better than I thought um uh
00:10:30.600 dependabot we we had a push to get a lot
00:10:32.680 of teams like sort of auto push through
00:10:34.839 dependabot minor gems if they pass tests
00:10:37.519 and that actually helped a lot with with
00:10:40.440 um most of our smaller gems like rails
00:10:42.959 upgrades are still complicated and and
00:10:44.600 things like that um for some reason we
00:10:46.800 have a lot of old gems that are pinning
00:10:48.680 an old version of rake that's eight
00:10:50.040 years out of date which looks bad on the
00:10:52.079 metric but doesn't actually affect
00:10:53.760 anything since we don't actually use
00:10:55.200 that for anything um so stuff like that
00:10:58.440 um it it was actually we actually were
00:11:00.079 able to point to doing better than I
00:11:01.760 thought and and using this tool as a
00:11:03.800 visualization we have been able to
00:11:05.680 encourage teams to move uh out of rails
00:11:08.800 and some other dependencies faster than
00:11:10.440 they have been beforehand um and another
00:11:12.639 thing is like it's very easy to forget
00:11:14.839 version pins uh you know there was a
00:11:17.320 there was a bug we set a ceiling on this
00:11:20.040 gem so that nobody would get to the bug
00:11:21.519 version but then the the followup of
00:11:23.440 somebody coming back six months later to
00:11:25.000 see if that bug has been fixed uh and we
00:11:27.560 can then continue to move forward like
00:11:29.760 that's the hard process and we're just
00:11:31.320 starting to put together some we just
00:11:33.440 have some visualizations that just went
00:11:34.880 up now um to like encourage that process
00:11:37.560 a little bit more so that's my part
00:11:41.000 thanks I will take we will take
00:11:42.160 questions together at the end um but I'm
00:11:44.279 going to pass it over to Brant who's
00:11:46.639 gonna talk about personal identifiable
00:11:57.160 information thanks n hi everyone um my
00:12:01.360 name is brand uh like n mentioned I
00:12:04.000 recently joined the iHeart Ruby team at
00:12:06.560 chime and it's uh been a really great
00:12:09.560 opportunity and just excited to be here
00:12:12.279 and share a little bit about what we've
00:12:14.000 been working
00:12:15.360 on so um the topic I'd like to share
00:12:18.639 about today is masking
00:12:22.880 pii so what is
00:12:25.560 pii um pii is an Acron for personally
00:12:30.279 identifiable information so this is just
00:12:33.120 any data that can be used to identify a
00:12:36.600 specific individual so this could be
00:12:38.399 like first and last name email social
00:12:41.240 security number and um a whole host of
00:12:44.600 things including like IDs like a
00:12:47.160 marketing ID for
00:12:48.959 example um as a quick aside I will share
00:12:52.079 a little bit of my
00:12:54.000 pii um I started writing Ruby in 17
00:13:00.440 those are the versions of um Ruby rails
00:13:03.600 that I was working with at the time and
00:13:07.079 I joined CH about two years ago but like
00:13:09.600 I mentioned um just recently joined
00:13:11.760 iHeart Ruby team in
00:13:14.000 September um this is my first time at
00:13:16.120 Ruby conf so really excited to be here
00:13:20.000 as a quick personal anecdote um I tried
00:13:23.760 to go to rails comp in 2020 and of
00:13:27.040 course that was cancelled for obvious
00:13:28.720 reasons
00:13:29.639 and then last year I tried to go to Ruby
00:13:31.560 conf and I was selected to serve on a
00:13:33.560 jury trial so it's been a long challenge
00:13:38.760 but finally I made it to a ruby
00:13:40.839 conference and then here's some of my uh
00:13:43.440 Ruby takes if you want to argue about
00:13:45.440 random stuff like that happy to do
00:13:49.160 so okay so most uh organizations handle
00:13:53.880 large volumes of customer pii so this is
00:13:56.880 a problem that I think a lot of folks
00:14:00.320 here can probably relate
00:14:01.800 to and um it's it's an important
00:14:06.680 Challenge and the problem again what
00:14:08.880 we're trying to solve stated here more
00:14:11.800 clearly is um how do we prevent pii from
00:14:14.600 entering logs and from being output so
00:14:19.120 how do we make sure we're not writing
00:14:20.880 pii in places we shouldn't be writing it
00:14:23.680 and how do we um offis it if for example
00:14:27.519 you're working in a terminal session
00:14:30.240 and you're you know in a production
00:14:32.079 environment sifting through
00:14:35.040 data so here's just a few examples um
00:14:37.880 you can see like what pii might look
00:14:40.680 like if it were to be masked or not um
00:14:44.320 there's different approaches but the
00:14:45.920 general idea is you want to offis enough
00:14:49.560 information so that it's no longer
00:14:52.000 personally identifiable but um it could
00:14:55.040 be nice for debugging purposes to still
00:14:57.079 leave a fragment of data
00:14:59.880 so that you can distinguish um two
00:15:01.600 different pieces of pii that might
00:15:03.600 otherwise look
00:15:05.839 identical so for example you could
00:15:07.759 include like the domain of an email
00:15:10.079 address but obate the the first half of
00:15:15.839 it so um what I'd like to do is just
00:15:18.600 dive into a couple of simple code
00:15:21.560 examples to illustrate how we're
00:15:23.320 thinking about this problem and some of
00:15:25.880 the techniques that we've been using to
00:15:28.680 handle
00:15:30.360 LP um there is a little bit of rails
00:15:33.040 here but I would say this is pretty
00:15:35.519 generalized and um some of these these
00:15:37.839 ideas can be applied outside of that and
00:15:40.360 in other
00:15:42.759 Frameworks so um this is a pretty simple
00:15:46.440 example of what we're hoping to
00:15:49.199 achieve um suppose you have like a user
00:15:52.160 object and maybe the user object has a
00:15:55.800 phone
00:15:57.000 attribute um what we like is
00:15:59.680 is for our logging purposes and in the
00:16:03.839 terminal we want to mask the value of
00:16:07.120 that phone
00:16:08.759 number um so what we might do is we
00:16:12.120 might like to introduce like a wrapper
00:16:14.399 object that handles that for us um and
00:16:17.800 that's sort of what this is proposing
00:16:19.120 here is that uh rather than just having
00:16:21.240 the phone number stored as a string um
00:16:23.920 have that introduce a layer of
00:16:25.560 indirections so that there's an object
00:16:27.240 containing that and then that object has
00:16:29.639 control over how that data is um
00:16:33.160 shown um so for example if you were to
00:16:35.440 interpolate that into a string then um
00:16:38.199 what you get is not the phone number
00:16:39.920 itself but the masked form of the phone
00:16:41.720 number and similarly if you were to call
00:16:43.839 a method like inspect um it's also going
00:16:46.240 to mask the
00:16:49.279 pii um so here's um a couple more
00:16:52.240 examples of what we would like so um we
00:16:56.480 definitely want to preserve certain
00:16:59.160 critical behaviors that you can your
00:17:03.160 code probably relies on like um method
00:17:06.400 calls like the present method or uh
00:17:09.919 value equality
00:17:12.799 comparisons um we want to preserve those
00:17:14.880 behaviors we don't want to get in the
00:17:15.919 way of that so um that's another
00:17:18.760 consideration for what this sort of
00:17:21.839 solution needs to
00:17:23.880 include and then finally um if you
00:17:26.760 needed to actually access
00:17:29.440 underlying um pii for whatever reason uh
00:17:33.039 there should still be a mechanism that
00:17:34.400 can provide
00:17:37.600 that so this is sort of like an example
00:17:41.160 very simplified example of what that
00:17:43.840 wrapper class could look like um so
00:17:47.559 we're referring to this as a maskable
00:17:50.360 value U this could be sort of like a
00:17:52.520 parent class and then um we could
00:17:55.080 introduce a hierarchy so there's derived
00:17:56.960 classes that inherit some of the
00:17:58.440 behavior but then maybe add um extra
00:18:03.159 tailored behavior for particular types
00:18:05.720 of Pi so like email or phone for
00:18:08.840 example um it's really simple just uh
00:18:12.760 you know introduce some instance
00:18:14.640 variables for the field and the raw
00:18:18.000 value and then um have like a method to
00:18:21.880 access the raw value sort of like an
00:18:23.640 escape
00:18:24.720 hatch if you need that behavior and then
00:18:28.880 the maskable value or sorry the masked
00:18:31.080 Value method is um what actually
00:18:33.320 performs the offis skating of the pii so
00:18:37.520 here's like a generalized form of that
00:18:41.520 um you know you can decorate however you
00:18:44.760 like but the idea is you say what kind
00:18:47.520 of field it is and then you just can say
00:18:49.840 that it's
00:18:53.240 redacted and then um in this code sample
00:18:56.880 this is illustrating what a child class
00:19:00.440 might look like so here um we can
00:19:03.840 override the mass or the mass Value
00:19:06.280 method and provide like a little bit
00:19:08.559 more
00:19:09.400 custom style of
00:19:12.120 masking so in the case of phone number
00:19:14.480 we can just grab the last four digits of
00:19:17.159 that phone number and interpolate that
00:19:19.919 into the
00:19:22.840 string so what do we do with what can we
00:19:26.799 do with this sort of um wrapper object
00:19:30.760 well one idea is we can integrate this
00:19:34.240 into our framework so um we could
00:19:37.400 introduce something like a rails uh
00:19:41.120 domain specific
00:19:42.600 language to um automatically perform
00:19:46.400 this wrapping for
00:19:47.880 us and um that's sort of what this is
00:19:50.919 trying to
00:19:52.080 accomplish so the idea here is like
00:19:55.600 let's suppose we introduce a method
00:19:57.679 called protect and this method can the
00:20:02.039 idea with this method is you give it a
00:20:03.799 rails attribute so if you have a rails
00:20:05.640 model like a user model and um it has an
00:20:09.640 attribute you want to protect you want
00:20:12.159 to wrap that with one of these maskable
00:20:14.679 classes then you can invoke the method
00:20:17.720 you can specify what the attribute is
00:20:21.360 and then you can optionally add sprinkle
00:20:24.640 in some um
00:20:26.559 other features like perhaps um you have
00:20:30.840 a mechanism where you can infer what
00:20:32.360 sort of type the um attribute is based
00:20:36.360 on its name so maybe you have like a
00:20:38.600 mapping or some sort of
00:20:40.679 Rex so having sort of like um a type
00:20:44.280 mapping from the attribute name to the
00:20:47.200 drive
00:20:48.280 class and then um you can also add
00:20:51.000 callbacks
00:20:53.159 to have support additional Behavior if
00:20:56.640 you want to um like invoke a meth method
00:20:59.039 before or after wrapping your
00:21:02.559 Pi um so that's this is kind of
00:21:04.640 illustrating what that might look
00:21:07.000 like and then here's an example of how
00:21:10.880 this could be applied so just a pretty
00:21:13.520 simple use case let's suppose you have
00:21:16.400 like um some domain object like a
00:21:19.000 contact that let's say it's an active
00:21:21.919 record or application
00:21:24.520 record um what we can do is invoke this
00:21:28.320 um method from our DSL protect and we
00:21:31.600 can specify which specific attributes we
00:21:35.279 want to protect and which ones we want
00:21:37.120 to wrap in pii and then um provide any
00:21:40.320 of the
00:21:41.320 additional uh additional optional
00:21:44.559 arguments that we
00:21:49.440 mentioned and then um one other thing
00:21:52.360 that we're thinking about is how would
00:21:54.679 we roll this out into a production
00:21:57.360 system with without breaking things and
00:22:01.480 causing Havoc so um the way that we're
00:22:05.039 thinking about doing this is by just
00:22:07.799 introducing some configuration options
00:22:11.279 so for example
00:22:13.559 um ultimately maybe you want to raise an
00:22:18.480 error if um unmasked pii is shown or is
00:22:24.360 used in production um but rather than
00:22:27.559 just mer merging that in and breaking
00:22:30.360 your service um having a a way of
00:22:33.480 detecting it and then isolating those um
00:22:36.600 call S sites so you can go in and fix it
00:22:39.559 is pretty important so by have
00:22:41.760 supporting different sort of strategies
00:22:44.120 we can make that um integration
00:22:48.720 easier um so for example what you might
00:22:50.840 have in the test environment is uh maybe
00:22:53.039 in a test environment you do want to
00:22:54.520 raise an error when uh pii is unass or
00:22:59.919 is accessed in unmasked way uh but then
00:23:02.679 in production maybe initially what you
00:23:04.559 want is to um log where that call is
00:23:08.159 happening and then allow the unmasked
00:23:11.960 call initially so that you can then go
00:23:14.799 back and go through the log and clean
00:23:16.880 things
00:23:19.240 up so this is uh one example of how this
00:23:24.360 configuration could be used so um this
00:23:28.600 would be like the two string method
00:23:31.120 override that's in the maskable value
00:23:34.000 parent
00:23:35.200 class and um you can see you just grab
00:23:38.240 this whatever strategy was set in
00:23:41.000 configuration and then um based on what
00:23:44.080 sort of strategy you have you can
00:23:46.080 either uh raise an error or perform
00:23:49.679 logging or simply return um The Mask
00:23:57.120 value and then
00:23:59.320 um lastly in the code samples this is
00:24:02.240 just a really simple illustration of um
00:24:05.799 what we would like to have for framework
00:24:08.559 like sidekick for example so
00:24:13.159 um basically the idea here is if we
00:24:16.760 introduce some sort of middleware so
00:24:19.279 that anytime um a sidekick job is called
00:24:23.880 uh we get this automatic wrapping of the
00:24:26.600 maskable objects
00:24:29.120 and um the idea is that then when your
00:24:32.600 job actually performs you get that
00:24:34.880 masking for free so the parameters you
00:24:38.000 pass in are not perhaps they're not
00:24:39.720 maskable objects but due to the
00:24:41.440 middleware stepping in it's able to wrap
00:24:44.039 them and provide that
00:24:49.000 protection cool and then um the last
00:24:51.520 thing I'll mention here is that one one
00:24:56.240 um alternative that we sort of looked
00:24:57.720 into
00:24:59.000 was this um idea of using parameter
00:25:01.720 filter which is um this is a object that
00:25:05.640 you can use it's already implemented in
00:25:07.880 active
00:25:08.919 support in rails um but basically what
00:25:12.080 this does is
00:25:14.480 you given um a hash like object with
00:25:18.480 keys you can um
00:25:21.880 specify a a list of like rejects or
00:25:25.399 strings or symbols to uh fill filter
00:25:28.720 from that hash
00:25:31.159 object um so this is a useful tool but
00:25:34.440 the the main issue that with this one is
00:25:38.240 it requires you to anticipate ahead of
00:25:41.480 time exactly the the form that your pii
00:25:45.720 is going to take and so um it places a
00:25:48.720 burd on the programmer to like specify
00:25:51.080 this comprehensive list of rexes or
00:25:54.000 strings to catch all possible matching
00:25:57.159 keys
00:25:59.240 and um so it's sort of like the
00:26:01.880 trade-off between a band list and an
00:26:03.640 allow list here this is sort of like the
00:26:05.320 band list approach and you're always
00:26:06.840 having to kind of play whack-a-mole and
00:26:09.399 think about new edge cases um
00:26:13.640 whereas um using like the maskall gem
00:26:16.520 for
00:26:17.200 example you can
00:26:19.480 explicitly protect your attributes by
00:26:24.039 enshrining them with the method calls
00:26:29.640 and I think that's all we had so thank
00:26:33.520 you
Explore all talks recorded at RubyConf 2024
+64